home *** CD-ROM | disk | FTP | other *** search
- ;* GUS.ASM
- ;*
- ;* Gravis Ultrasound Sound Device
- ;*
- ;* $Id: gus.asm,v 1.3 1997/01/16 18:41:59 pekangas Exp $
- ;*
- ;* Copyright 1996,1997 Housemarque Inc.
- ;*
- ;* This file is part of the MIDAS Sound System, and may only be
- ;* used, modified and distributed under the terms of the MIDAS
- ;* Sound System license, LICENSE.TXT. By continuing to use,
- ;* modify or distribute this file you indicate that you have
- ;* read the license and understand and accept it fully.
- ;*
-
- comment #
-
- Preliminary InterWave support added on 08-Mar-1996
- by Jarno Petteri Heikkinen (japehe@cc.jyu.fi)
-
- historical notes:
-
- 13/04/96 "upgraded" gus code from pre-release 4
-
- 10/03/96 made somewhat "midas compliant" by defining two different
- cards (gusCardTypes)
- support for InterWave's >4MB memory does not exist
- (cant test it anyway, I have only 2MB)
-
- 08/03/96 I dont have a clue about how MIDAS Surround thing works
- so it prolly doesnt :)
-
- #
-
- IDEAL
- P386
- JUMPS
-
- INCLUDE "lang.inc"
- INCLUDE "errors.inc"
- INCLUDE "sdevice.inc"
- INCLUDE "mmem.inc"
- INCLUDE "mglobals.inc"
- INCLUDE "mutils.inc"
-
- ; This switch determines whether GUS SoundDevice should use full volume
- ; ramps when setting instruments (no clicks, but slower) or just faster
- ; ramping. Value 1 sets fast ramps.
-
- FASTGUS = 0
-
- ;/***************************************************************************\
- ;* enum gusFunctIDs
- ;* ----------------
- ;* Description: ID numbers for GUS Sound Device functions
- ;\***************************************************************************/
-
- enum gusFunctIDs \
- ID_gusDetect = ID_gus, \
- ID_gusInit, \
- ID_gusClose, \
- ID_gusGetMixRate, \
- ID_gusGetMode, \
- ID_gusOpenChans, \
- ID_gusCloseChans, \
- ID_gusClearChans, \
- ID_gusMute, \
- ID_gusPause, \
- ID_gusSetMasterVolume, \
- ID_gusGetMasterVolume, \
- ID_gusSetAmplification, \
- ID_gusGetAmplification, \
- ID_gusPlaySound, \
- ID_gusReleaseSound, \
- ID_gusStopSound, \
- ID_gusSetRate, \
- ID_gusGetRate, \
- ID_gusSetVolume, \
- ID_gusGetVolume, \
- ID_gusSetSample, \
- ID_gusGetSample, \
- ID_gusSetPosition, \
- ID_gusGetPosition, \
- ID_gusGetDirection, \
- ID_gusSetPanning, \
- ID_gusGetPanning, \
- ID_gusMuteChannel, \
- ID_gusAddSample, \
- ID_gusRemoveSample, \
- ID_gusSetUpdRate, \
- ID_gusStartPlay, \
- ID_gusPlay, \
- ID_gusInitHeap, \
- ID_gusFreeHeap, \
- ID_gusMalloc, \
- ID_gusFree, \
- ID_gusAllocBlock, \
- ID_gusCoreFree
-
-
- ;/***************************************************************************\
- ;* ENUM gusCardTypes
- ;* ----------------
- ;* Description: Sound Card type number for GUS Sound Device
- ;\***************************************************************************/
-
- enum gusCardTypes \
- gusAutoType = 0, \ ; autodetect card type
- gusGF1, \ ; original GF1 based card
- gusIW ; AMD InterWave based card
-
-
- DATASEG
-
- IFDEF __PASCAL__
- EXTRN GUS:SoundDevice
- ENDIF
-
- STRUC gusInstrument
- D_int sampleType ; sampleType
- D_long sample ; ptr to sample in GUS mem
- D_long surround ; ptr to surround sample in GUS mem / 0
- D_int length ; length in bytes
- D_int loopMode ; See enum
- D_int loopNum ; In loop 1/2 (0 if not looped [anymore])
- D_int loop1Type ; See enum
- D_int loop1Start ; Offset from beg.
- D_int loop1End ; Offset from beg.
- D_int loop2Type ; See enum
- D_int loop2Start ; Offset from beg.
- D_int loop2End ; Offset from beg.
- ENDS
-
-
-
- ; STATUS BITS:
-
- enum gusStatusBits \
- gsStop = 1, \ ; Stop voice
- gsRetrig = 2, \ ; Retrig note
- gsVolume = 4, \ ; Set volume
- gsFC = 8, \ ; Set FC
- gsSample = 16, \ ; Sample changed
- gsOnOff = 32, \ ; Sample on/off (used for pause)
- gsPanning = 64, \ ; Set panning
- gsMute = 128, \ ; Muted
- gsReleased = 256 ; Note released
-
-
-
- STRUC gusChannel
- D_int status ; See enum above
- D_int inst ; Number
- D_int curinst ; Current instrument playing
- D_int fc ; In FC-format
- D_long frequency ; In Hz
- D_int volume ; 0-64
- D_int surround ; Surround flag
- D_int sampleType ; See enum
- D_int loopMode ; See enum
- D_int loop1Type ; See enum
- D_int loop2Type ; See enum
- D_long scurrent ; Current position for GUS
- D_long sstart ; Sample start for GUS
- D_long send ; Sample end for GUS
- D_long l2start ; Loop 2 start for GUS
- D_long l2end ; Loop 2 end for GUS
- D_int panning ; Panning position (see enum)
- D_int panningHW ; Panning hardware value
- D_int onoff ; On / Off switch (DEBUG!)
- ENDS
-
-
- STRUC ghb ; GUS Heap Block
- D_long next ; Pointer to next block
- D_long gusmem ; Pointer to GUS memory
- D_long length ; Length of this block (Rounded to 32 byte border)
- ENDS
-
- ; lengthFlags:
- ; 0 free / allocated
-
-
-
- D_int chancount ; Amount of channels
- D_int voicesel ; Voice Select register
- D_int selreg ; Select Register
-
- D_int mixfreq ; Mixing frequency
- D_int updRate ; SD update rate
-
- D_int instpos ; Instrument to be filled next
-
- D_int muted ; 0 = unmuted, 1 = muted
- D_int paused ; 0 = not, 1 = paused
- D_int mastervol ; Default = max
- D_int masterchanged ; Overrides channel set volume
- D_int numInsts ; Max instrument.
-
- D_long memamount ; Amount of memory on GUS
- D_long memavail ; Memory available on GUS
- D_long largestblock ; Largest block of memory on GUS
- D_long gusHeapStart ; First block of GUS heap
- D_long gusHeap ; Pointer to GUS heap
- D_int monoFlag ; Force mono output
- D_long temp ; Temporary storage
- D_int flag ; Internal flag
- D_int chansOpen ; channels open flag
- D_int gusAmp ; amplification value
-
- label channels gusChannel
- rept 32
- gusChannel ?
- endm
-
- D_long Instruments ; Pointer to GUS instruments
-
-
-
- IDATASEG
-
-
- ; If compiling for Pascal, Sound Device name is gusSD, from which the data
- ; will be copied to Sound Device GUS, defined in Pascal.
-
- IFDEF __PASCAL__
- SDNAM equ gusSD
- ELSE
- SDNAM equ GUS
- ENDIF
-
-
- GLOBAL SDNAM : SoundDevice
-
- ; sdMono or sdStereo or sd16bit, \
-
- SDNAM SoundDevice < \
- 1, \ ; Called according to tempo
- sdUsePort or sdUseOutputMode, \
- 220h, 0, 0, \ ; Port, IRQ, DMA
- gusAutoType, 2,\ ; Card, num.cards
- sdMono or sdStereo or sd16bit, \
- ptr_to gusSDName, \
- ptr_to gusCardNames, \
- 6, ptr_to gusPortAddresses, \
- ptr_to gusDetect, \
- ptr_to gusInit, \
- ptr_to gusClose, \
- ptr_to gusGetMixRate, \
- ptr_to gusGetMode, \
- ptr_to gusOpenChans, \
- ptr_to gusCloseChans, \
- ptr_to gusClearChans, \
- ptr_to gusMute, \
- ptr_to gusPause, \
- ptr_to gusSetMasterVolume, \
- ptr_to gusGetMasterVolume, \
- ptr_to gusSetAmplification, \
- ptr_to gusGetAmplification, \
- ptr_to gusPlaySound, \
- ptr_to gusReleaseSound, \
- ptr_to gusStopSound, \
- ptr_to gusSetRate, \
- ptr_to gusGetRate, \
- ptr_to gusSetVolume, \
- ptr_to gusGetVolume, \
- ptr_to gusSetSample, \
- ptr_to gusGetSample, \
- ptr_to gusSetPosition, \
- ptr_to gusGetPosition, \
- ptr_to gusGetDirection, \
- ptr_to gusSetPanning, \
- ptr_to gusGetPanning, \
- ptr_to gusMuteChannel, \
- ptr_to gusAddSample, \
- ptr_to gusRemoveSample, \
- ptr_to gusSetUpdRate, \
- ptr_to gusStartPlay, \
- ptr_to gusPlay >
-
- gusSDName DB "Gravis Ultrasound Sound Device v4.10",0
-
- gusCardNames DD ptr_to gusName
- DD ptr_to iwName
-
- ;gusName DB "Gravis GF1 (Compatible mode)", 0
- ;iwName DB "AMD InterWave (Enhanced mode)", 0
- gusName DB "Gravis UltraSound (GF1 Hardware mixing)",0
- iwName DB "GUS PnP (AMD Interwave Hardware mixing)",0
-
- IFDEF __16__
- gusPortAddresses DW 210h, 220h, 230h, 240h, 250h, 260h
- ELSE
- gusPortAddresses DD 210h, 220h, 230h, 240h, 250h, 260h
- ENDIF
-
- gusIRQAddresses db 2, 3, 5, 7, 11, 12, 15
- gusIRQints db 71h, 0bh, 0dh, 0fh, 73h, 74h, 77h
-
-
- ; gusInterrupt db 0 ; fuck
-
- env DB "ULTRASND",0
- env_iw DB "INTERWAVE", 0
-
- ; Mixing frequencies for channel amounts 14-32
-
- chantab dw 44100,41160,38587,36317,34300,32494,30870,29400,28063,26843
- dw 25725,24696,23746,22866,22050,21289,20580,19916,19293
-
-
-
- LABEL voltable WORD
- dw 01500h,08f10h,09f10h,0ab50h,0af10h,0b970h,0bb50h,0bd30h
- dw 0bf10h,0c880h,0c970h,0ca60h,0cb50h,0cc40h,0cd30h,0ce20h
- dw 0cf10h,0d800h,0d880h,0d8f0h,0d970h,0d9e0h,0da60h,0dad0h
- dw 0db50h,0dbc0h,0dc40h,0dcb0h,0dd30h,0dda0h,0de20h,0de90h
- dw 0df10h,0df80h,0e800h,0e840h,0e880h,0e8b0h,0e8f0h,0e930h
- dw 0e970h,0e9a0h,0e9e0h,0ea20h,0ea60h,0ea90h,0ead0h,0eb10h
- dw 0eb50h,0eb80h,0ebc0h,0ec00h,0ec40h,0ec70h,0ecb0h,0ecf0h
- dw 0ed30h,0ed60h,0eda0h,0ede0h,0ee20h,0ee50h,0ee90h,0eed0h
- dw 0ef00h
-
- ; Louder volume table
-
- IF 0
- dw 01500h,09c10h,0ac10h,0b910h,0bc10h,0bf10h,0c910h,0ca90h
- dw 0cc10h,0cd90h,0cf10h,0d850h,0d910h,0d9d0h,0da90h,0db50h
- dw 0dc10h,0dcd0h,0dd90h,0de50h,0df10h,0dfd0h,0e850h,0e8b0h
- dw 0e910h,0e970h,0e9d0h,0ea30h,0ea90h,0eaf0h,0eb50h,0ebb0h
- dw 0ec10h,0ec70h,0ecd0h,0ed30h,0ed90h,0edf0h,0ee50h,0eeb0h
- dw 0ef10h,0ef70h,0efd0h,0f820h,0f850h,0f880h,0f8b0h,0f8e0h
- dw 0f910h,0f940h,0f970h,0f9a0h,0f9d0h,0fa00h,0fa30h,0fa60h
- dw 0fa90h,0fac0h,0faf0h,0fb20h,0fb50h,0fb80h,0fbb0h,0fbe0h
- dw 0fc00h
- ENDIF
-
- ; Panning table for InterWave (pan registers are logarithmic too !!!)
- label pantable word
- dw 0FFF0h, 06FD0h, 05FD0h, 05670h, 04FD0h, 04AB0h, 04670h, 042E0h
- dw 03FD0h, 03D20h, 03AB0h, 03870h, 03670h, 034A0h, 032E0h, 03150h
- dw 02FD0h, 02E70h, 02D20h, 02BE0h, 02AB0h, 02990h, 02870h, 02770h
- dw 02670h, 02580h, 024A0h, 023C0h, 022E0h, 02210h, 02150h, 02090h
- dw 01FD0h, 01F20h, 01E70h, 01DC0h, 01D20h, 01C70h, 01BE0h, 01B40h
- dw 01AB0h, 01A20h, 01990h, 01900h, 01870h, 017F0h, 01770h, 016F0h
- dw 01670h, 01600h, 01580h, 01510h, 014A0h, 01430h, 013C0h, 01350h
- dw 012E0h, 01280h, 01210h, 011B0h, 01150h, 010F0h, 01090h, 01030h
- label pantablemid word
- dw 00FD0h, 00F70h, 00F20h, 00EC0h, 00E70h, 00E10h, 00DC0h, 00D70h
- dw 00D20h, 00CD0h, 00C70h, 00C30h, 00BE0h, 00B90h, 00B40h, 00AF0h
- dw 00AB0h, 00A60h, 00A20h, 009D0h, 00990h, 00940h, 00900h, 008C0h
- dw 00870h, 00830h, 007F0h, 007B0h, 00770h, 00730h, 006F0h, 006B0h
- dw 00670h, 00640h, 00600h, 005C0h, 00580h, 00550h, 00510h, 004D0h
- dw 004A0h, 00460h, 00430h, 003F0h, 003C0h, 00380h, 00350h, 00320h
- dw 002E0h, 002B0h, 00280h, 00250h, 00210h, 001E0h, 001B0h, 00180h
- dw 00150h, 00120h, 000F0h, 000C0h, 00090h, 00060h, 00030h, 00000h,0
-
-
-
- CODESEG
-
- ;******* GUS Register Select - Macro ************
-
- MACRO regsel register
- mov _dx,[selreg]
- mov al,register
- out dx,al
- ENDM
-
- ;******* GUS-delay subroutine ************
-
- PROC gusdelay NEAR
- push dx ax
- mov dx,300h
- rept 8
- in al,dx
- endm
- pop ax dx
- ret
- ENDP
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int gusDetect(int *result)
- ;*
- ;* Description: Detects Gravis UltraSound and fills in GUS SoundDevice
- ;* structure with appropriate values for port, DMA and IRQ
- ;*
- ;* Returns: MIDAS error code.
- ;* 1 stored to *result if GUS was detected, 0 if not.
- ;*
- ;\***************************************************************************/
-
- PROC gusDetect _funct result : _ptr
- USES _bx
-
- ; interwave detect
- cmp [GUS.cardType],gusAutoType ; has a card type been set?
- jne @@cardtypeset ; if not, detect it
-
- ; this finds out if there's INTERWAVE env str set and forces
- ; native interwave mode if it exists... dunno about better way to detect ;)
-
- IFDEF __16__
- call mGetEnv LANG, seg env offset env_iw
- mov bx,ax
- or bx,dx
- ELSE
- call mGetEnv LANG, ptr_to env_iw
- test _ax, _ax
- ENDIF
- mov _dx, gusGF1
- jz @@plaingus
- mov _dx, gusIW
- @@plaingus:
- mov [GUS.cardType], _dx
- @@cardtypeset:
-
- IFDEF __16__
- call mGetEnv LANG, seg env offset env
- mov bx,ax
- or bx,dx
- jz @@noGUS
- mov bx,ax
- mov es,dx ; point es:bx to environment string
- ELSE
- call mGetEnv LANG, ptr_to env
- test eax,eax
- jz @@noGUS
- mov ebx,eax
- ENDIF
- mov cl,3 ; 3 digits
- xor _ax,_ax
- @@dloop:
- mov dl,[_esbx]
- inc _bx
- sub dl,"0"
- shl _ax,4
- add al,dl
- dec cl
- jnz @@dloop
- mov [GUS.port],_ax
- ;
- ; mov cl, 3 ; now skip three commas
- ;@@comma:
- ; mov al, [_esbx]
- ; inc _bx
- ; test al, al ; if zero the ULTRASND env is wrong
- ; jz @@noGUS
- ; cmp al, ','
- ; jnz @@comma
- ; dec cl
- ; jnz @@comma
- ;
- ; mov al,[_esbx] ; first irq digit (skip comma)
- ; sub al,"0"
- ; mov ah, 10
- ; cmp [byte _esbx+1], ','
- ; jz @@onedigitirq
- ; imul ah
- ; add al,[_esbx+1] ; second irq digit is necessary
- ; sub al,"0"
- ;@@onedigitirq:
- ; xor ah, ah
- ; xor _bx, _bx
- ;@@scanirqlist:
- ; cmp [gusIRQAddresses+_bx], al
- ; jz @@scanirqfound
- ; inc _bx
- ; cmp _bx, 7
- ; jb @@scanirqlist
- ; jmp @@noGUS
- ;@@scanirqfound:
- ; cmp al, 2
- ; jnz @@not2nd
- ; mov al, 9
- ;@@not2nd:
- ; mov [GUS.IRQ],_ax
- ;
- ; mov al, [gusIRQints+_bx] ; translate irq to interrupt number
- ; mov [gusInterrupt], al
- ; inc bl ; irq ports start from 0 unlike our irq list
- ; mov _dx, [GUS.port]
- ; add dl, 0bh ; irq control register
- ; mov al, bl
- ; out dx, al
- ;
-
- ; Test if there really is a GUS
-
- add _ax,103h
- mov [selreg],_ax ; Register select (2x0h+103h)
-
- call gusReset
-
- regsel 44h
- add _dx,2
- xor _ax,_ax
- out dx,al ; upper bits of address
-
- regsel 43h
- inc _dx
- xor _ax,_ax ; Address 0
- out dx,ax
- add _dx,3
- mov al,055h
- out dx,al ; Poke data 1 (55h)
-
- sub _dx,3
- mov _ax,1 ; Address 1
- out dx,ax
- add _dx,3
- mov al,0AAh
- out dx,al ; Poke data 2 (AAh)
-
- sub _dx,3
- xor _ax,_ax ; Address 0
- out dx,ax
- add _dx,3
- in al,dx ; Peek data 1
- cmp al,055h
- jne @@noGUS
-
- sub _dx,3
- mov _ax,1 ; Address 1
- out dx,ax
- add _dx,3
- in al,dx ; Peek data 2
- cmp al,0AAh
- je @@found
-
- @@noGUS:
- mov [GUS.port],0
- xor _ax,_ax ; No GUS found
- jmp @@quit
-
- @@found:
- mov _ax,1 ; GUS found
- @@quit:
- LOADPTR es,_bx,[result]
- mov [_esbx],_ax
- xor _ax,_ax
- ret
- ENDP
-
- ;/***************************************************************************\
- ;*
- ;* Function: int gusInit(int rate, int mode)
- ;*
- ;* Description: Initializes the GUS for playing
- ;*
- ;* Input: int rate Mixing rate (no effect on GUS)
- ;* int mode Mode (see enum) (mono flag only)
- ;*
- ;* Returns: MIDAS error code.
- ;*
- ;\***************************************************************************/
-
- PROC gusInit _funct rate : _int, mode : _int
- USES _di,_bx
-
- mov [instpos],1 ; First instrument to be filled
- mov [numInsts],0 ; No instruments
- mov [mastervol],64 ; Default master volume
- mov [masterchanged],0
- mov [flag],0
- mov [chansOpen],0
-
- mov _ax,[mode]
- and _ax,sdMono ; AND mono bit
- mov [monoFlag],_ax ; 1 if mono, 0 otherwise
-
- ; mov [monoFlag],0
-
- mov _ax,[GUS.port] ; Base address (Set before!)
- add _ax,103h
- mov [selreg],_ax ; Register select (2x0h+103h)
- dec _ax
- mov [voicesel],_ax ; Voice select (2x0h+102h)
-
- call gusReset ; Reset GUS
-
- cmp [GUS.cardType], gusIW
- jnz @@noiwfound ; interwave init?
-
- ; interwave to enhanced mode (19h bit 0)
- regsel 19h
- add _dx, 2
- mov al, 01h ; set enhanced mode
- out dx, al
- @@noiwfound:
-
- mov [memamount],0 ; Initial memory amount
- mov _cx,64 ; Max amount of 256k chunks(IW)
- xor _bx,_bx ; Start from 00000h
-
- @@memloop:
- regsel 44h
- add _dx,2
- mov _ax,_bx
- out dx,al ; upper bits of address
-
- regsel 43h
- inc _dx
- xor _ax,_ax ; Address 0
- out dx,ax
- add _dx,3
- mov al,055h
- out dx,al ; Poke data 1 (55h)
-
- sub _dx,3
- mov _ax,1 ; Address 1
- out dx,ax
- add _dx,3
- mov al,0AAh
- out dx,al ; Poke data 2 (AAh)
-
- sub dx,3
- xor _ax,_ax ; Address 0
- out dx,ax
- add _dx,3
- in al,dx ; Peek data 1
- cmp al,055h
- jne @@poiss
-
- sub _dx,3
- mov _ax,1 ; Address 1
- out dx,ax
- add _dx,3
- in al,dx ; Peek data 2
- cmp al,0AAh
- jne @@poiss
-
- add [memamount],256*1024 ; Add amount of memory by 256k
- add _bx,4 ; Next 256k chunk
- dec _cx
- jnz @@memloop
-
- @@poiss: ; No more memory
- cmp [memamount],0
- jne @@memok ; NO MEMORY!
-
- mov _ax,errSDFailure ; NO GUS
- jmp @@err
-
- @@memok:
- mov eax,[memamount] ; Initialize mem variables
- mov [memavail],eax
- mov [largestblock],eax
-
-
- ; Clear the all 32 channels
-
- mov _dx,[GUS.port] ; Mixer
- mov al,3
- out dx,al ; Disable Line in & out
-
- regsel 0eh
- add _dx,2
- mov al,31 OR 0c0h
- out dx,al ; Set number of active
- ; voices to 32 just for
- ; sure
-
- mov _cx,32 ; Number of voices
- @@resetloop:
- mov _dx,[voicesel] ; Voice Select
- mov _ax,_cx
- out dx,al
-
- regsel 0 ; Voice control
- add _dx,2 ; data low
- mov al,3 ; Stop voice
- out dx,al
-
- regsel 9 ; Current Volume
- inc _dx ; data high
- mov _ax,0500h ; Zero volume
- out dx,ax
-
- regsel 12 ; Pan Position
- add _dx,2 ; data low
- mov al,8 ; Center
- out dx,al
-
- regsel 13 ; Volume Ramping
- add _dx,2 ; data low
- mov al,3 ; disable
- out dx,al
-
- regsel 6 ; Ramp Rate
- add _dx,2
- mov al,3fh ; Rate
- out dx,al
-
- cmp [GUS.cardType], gusIW
- jnz @@noiwregs
-
- regsel 15h ;interwave synth mode select
- add _dx, 2
- mov al, 22h ; deactivate voice (bit 1), enhanced panning (bit 5)
- out dx, al
-
- regsel 10h ;interwave synth upper addr
- add _dx, 2
- xor eax, eax
- out dx, al
-
- regsel 13h ;interwave synth left offset
- inc dl
- mov bx, [pantablemid]
- mov ax, bx
- out dx, ax
- regsel 1ch
- inc dl
- mov ax, bx
- out dx, ax
-
- regsel 0ch ;interwave synth right offset
- inc dl
- mov ax, bx
- out dx, ax
- regsel 1bh
- inc dl
- mov ax, bx
- out dx, ax
- @@noiwregs:
- dec _cx
- jnz @@resetloop
-
- regsel 4ch ; RESET
- add _dx,2
- mov al,3
- out dx,al ; Enable GF1 and DACs
-
- mov _dx,[GUS.port]
- xor al,al
- out dx,al ; Enable line in and out
-
- call initHeap ; Initialize GUS-heap
- test _ax,_ax
- jne @@err
-
- IFDEF __16__
- call memAlloc LANG, MAXSAMPLES * SIZE gusInstrument,\
- seg temp offset temp ; Alloc room for instruments
- ELSE
- call memAlloc LANG, MAXSAMPLES * SIZE gusInstrument,\
- ptr_to temp ; Alloc room for instruments
- ENDIF
- test _ax,_ax
- jne @@err
-
- COPYPTR [Instruments],[temp]
-
- LOADPTR es,_di,[Instruments]
- IFDEF __32__
- push ds
- pop es
- ENDIF
- xor _ax,_ax
- mov _cx,MAXSAMPLES * SIZE gusInstrument
- cld
- rep stosb ; Clear instrument datas
- xor _ax,_ax
- ret
-
- @@err: ERROR ID_gusInit ; Heap error
- ret
- ENDP
-
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: gusReset
- ;*
- ;* Description: Resets the GUS card
- ;*
- ;* Destroys: al, dx
- ;*
- ;* FOR GUS SOUNDDEVICE INTERNAL USE ONLY!
- ;*
- ;\***************************************************************************/
-
- PROC gusReset NEAR
- regsel 4ch ; RESET
- add _dx,2
- xor al,al
- out dx,al ; RESET!
-
- call gusdelay
- call gusdelay
-
- mov al,1
- out dx,al ; Enable GF1
-
- call gusdelay
- call gusdelay
- ret
- ENDP
-
- ;/***************************************************************************\
- ;*
- ;* Function: int gusClose()
- ;*
- ;* Description: Closes up the GUS.
- ;*
- ;* Returns: MIDAS error code.
- ;*
- ;\***************************************************************************/
-
- PROC gusClose _funct
- USES _bx
-
- call gusReset
-
- regsel 19h ; interwave to gus mode
- add _dx, 2
- xor al, al ; set gus compatible mode
- out dx, al
-
- mov _dx,[GUS.port] ; Mixer
- xor al,al
- out dx,al ; Enable Line in & out
-
- call freeHeap
- test _ax,_ax
- jnz @@err
-
- call memFree LANG, [Instruments] ; Free instruments
- test _ax,_ax
- jnz @@err
-
- mov [instpos],1 ; Flush instruments
- ret ; ax already 0
-
- @@err: ERROR ID_gusClose
- ret
- ENDP
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int gusGetMixRate(int *rate)
- ;*
- ;* Description: Returns the mixing rate of the SD
- ;*
- ;* Returns: MIDAS error code.
- ;* Mixing rate is written to *rate.
- ;*
- ;\***************************************************************************/
-
- PROC gusGetMixRate _funct rate : _ptr
- USES _bx
-
- mov _ax,[mixfreq] ; Get mixing rate
- LOADPTR es,_bx,[rate]
- mov [_esbx],_ax
- xor _ax,_ax ; Can't fail
- ret
- ENDP
-
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int gusGetMode(int *mode)
- ;*
- ;* Description: Returns the output mode
- ;*
- ;* Returns: MIDAS error code.
- ;* Output mode is written to *mode.
- ;*
- ;\***************************************************************************/
-
- PROC gusGetMode _funct mode : _ptr
- USES _bx
-
- mov _ax,sd16bit
- mov _bx,2
- sub _bx,[monoFlag] ; 1 if mono (=sdMono)
- ; 2 if not (=sdStereo)
- or _ax,_bx
- LOADPTR es,_bx,[mode]
- mov [_esbx],_ax
- xor _ax,_ax ; Can't fail
- ret
- ENDP
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int gusOpenChans(int chans)
- ;*
- ;* Description: Opens channels from the GUS
- ;*
- ;* Input: int chans Number of channels to open
- ;*
- ;* Returns: MIDAS error code.
- ;*
- ;\***************************************************************************/
-
- PROC gusOpenChans _funct chans : _int
- USES _si,_di,_bx
-
- mov [gusAmp],64
-
-
- mov _bx,[chans]
- mov [chancount],_bx
-
- mov [muted],0
- mov [paused],0
-
- IFNDEF NOSTEREO
- cmp [mEnableSurround],0
- je @@nsurr
- add _bx,_bx
- cmp _bx,32
- ja @@err
- @@nsurr:
- ENDIF
- cmp _bx,14
- jae @@okei
- mov _bx,14 ; At least 14 channels open
- @@okei:
- mov _cx,_bx
-
- sub _bx,14
- add _bx,_bx
- mov bx,[chantab+_bx] ; Take the mixing rate
-
- cmp [GUS.cardType], gusIW
- jnz @@noiwmixrate
- mov _bx, 44100 ; interwave is always 44.1kHz
- @@noiwmixrate:
- mov [mixfreq],_bx
-
- regsel 0eh
- add _dx,2
- mov _ax,_cx
- dec _ax ; Amount-1
- or al,0c0h
- out dx,al
-
- mov _ax,ds
- mov es,_ax
- mov _di,offset channels
- xor al,al
- cld
- mov _cx,size gusChannel*32
- rep stosb ; Clear channel blocks
-
- mov _cx,[chans] ; to the table
- xor _bx,_bx ; Start from channel 0
- @@panloop:
- mov _dx,[voicesel] ; Voice Select
- mov _ax,[chans]
- sub _ax,_cx
- out dx,al
-
- regsel 12 ; Pan Position
- add _dx,2 ; data low
-
- mov [_bx+channels.panning],panMiddle ; Panning position
-
- mov al,8 ; Middle
- out dx,al
-
- cmp [GUS.cardType], gusIW
- jnz @@noiwregs
-
- ; interwave synth mode select
- regsel 15h
- add _dx, 2
- mov al, 20h ; activate voice, select enhanced panning
- out dx, al
- ; interwave synth right offset ( bigger blocks sound )
- regsel 0ch
- inc dl
- mov ax, [pantablemid]
- out dx, ax
- regsel 1bh ; right offset fine
- inc dl
- mov ax, [pantablemid]
- out dx, ax
- ; interwave synth left offset
- regsel 13h ; left offset
- inc dl
- mov ax, [pantablemid]
- out dx, ax
- regsel 1ch ; left offset fine
- inc dl
- mov ax, [pantablemid]
- out dx, ax
-
- @@noiwregs:
-
- mov [_bx+channels.status],gsStop
- cmp [mEnableSurround],0
- je @@nss
-
- mov _ax,[chancount]
- imul _ax,_ax,size gusChannel ; Get surround chan
- mov _si,_ax
- add _si,_bx
- mov [_si+channels.status],gsMute OR gsStop
-
- @@nss: add _bx,SIZE gusChannel
- dec _cx
- jnz @@panloop
-
- mov [chansOpen],1
-
- mov _dx,[GUS.port]
- xor al,al
- out dx,al ; Enable line in and out
-
- call gusMute LANG, 0
- test _ax,_ax
- jnz @@err2
- ret
-
- @@err: mov _ax,errNoChannels ; Too much channels
- @@err2: ERROR ID_gusOpenChans
- ret
- ENDP
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int gusCloseChans()
- ;*
- ;* Description: Closes channels from the GUS
- ;*
- ;* Returns: MIDAS error code.
- ;*
- ;\***************************************************************************/
-
- PROC gusCloseChans _funct
- USES _bx
-
- call gusClearChans LANG
- mov [chansOpen],0
- mov [chancount],0
- xor _ax,_ax ; Can't fail
- ret
- ENDP
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int gusClearChans()
- ;*
- ;* Description: Clears the channels from the GUS
- ;*
- ;* Returns: MIDAS error code.
- ;*
- ;\***************************************************************************/
-
- PROC gusClearChans _funct
- USES _si,_bx
-
- xor _bx,_bx
- mov _cx,[chancount]
- @@clloop:
- mov _dx,[voicesel] ; Voice Select
- mov _ax,[chancount]
- sub _ax,_cx
- out dx,al
-
- regsel 0 ; Voice control
- add _dx,2
- mov al,3
- out dx,al ; Stop sound
-
- call gusdelay
-
- out dx,al ; Stop sound
-
- regsel 12 ; Pan Position
- add _dx,2 ; data low
-
- mov [_bx+channels.panning],panMiddle ; Panning position
- mov [_bx+channels.inst],0 ; No instrument
- mov [_bx+channels.curinst],0 ; No instrument
- mov [_bx+channels.status],gsStop
-
- mov al,8 ; Middle
- out dx,al
-
- cmp [GUS.cardType], gusIW
- jnz @@noiwregs
- ; interwave synth mode select
- regsel 0ch
- add dl, 2
- mov al, 2 ; de-active channel
- out dx, al
- ; interwave synth right offset
- regsel 0ch
- inc dl
- mov ax, [pantablemid]
- out dx, ax
- regsel 1bh ; right offset fine
- inc dl
- mov ax, [pantablemid]
- out dx, ax
- ; interwave synth left offset
- regsel 13h ; left offset
- inc dl
- mov ax, [pantablemid]
- out dx, ax
- regsel 1ch ; left offset fine
- inc dl
- mov ax, [pantablemid]
- out dx, ax
- @@noiwregs:
-
-
- IFNDEF NOSTEREO
- cmp [mEnableSurround],0
- je @@nss
-
- mov _ax,[chancount]
- imul _ax,_ax,size gusChannel ; Get surround chan
- mov _si,_ax
- add _si,_bx
- mov [_si+channels.status],gsMute OR gsStop
-
- mov _dx,[voicesel] ; Voice Select
- mov _ax,[chancount]
- add _ax,_ax ; Surround channel
- sub _ax,_cx
- out dx,al
-
- regsel 0 ; Voice control
- add _dx,2
- mov al,3
- out dx,al ; Stop sound
-
- call gusdelay
-
- out dx,al ; Stop sound
-
- @@nss:
- ENDIF
- add _bx,SIZE gusChannel
- dec _cx
- jnz @@clloop
- xor _ax,_ax ; Can't fail
- ret
- ENDP
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int gusMute(ushort mute)
- ;*
- ;* Description: Mutes/unmutes GUS Sound Device
- ;*
- ;* Input: int mute UnMute = 0 / Mute = 1
- ;*
- ;* Returns: MIDAS error code.
- ;*
- ;\***************************************************************************/
-
- PROC gusMute _funct mute : _int
- USES _bx
-
- mov _ax,[mute]
- cmp [muted],_ax
- je @@done ; Already at that state
- mov [muted],_ax
- mov bl,1 ; Enable GF1 (Disable DACs)
- test _ax,_ax
- jnz @@mute
- mov bl,3 ; Enable DACs (unmute)
- @@mute: cli
- regsel 4ch ; RESET
- add _dx,2
- mov al,bl
- out dx,al
- sti
- @@done: xor _ax,_ax ; Can't fail
- ret
- ENDP
-
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int gusPause(ushort pause)
- ;*
- ;* Description: Pauses/unpauses GUS SD
- ;*
- ;* Input: int pause Unpause = 0 / Pause = 1
- ;*
- ;* Returns: MIDAS error code.
- ;*
- ;\***************************************************************************/
-
- PROC gusPause _funct pause : _int
- USES _bx
-
- mov _ax,[pause]
- cmp [paused],_ax
- je @@done ; Already at that state
- mov [paused],_ax
- test _ax,_ax
- jnz @@pause
-
- xor _cx,_cx
- xor _bx,_bx
- @@chloop:
- test [_bx+channels.status],gsOnOff
- jz @@off
-
- cli
- mov _dx,[voicesel] ; Select voice
- mov _ax,_cx
- out dx,al
-
- regsel 0
- add _dx,2
- mov _ax,[_bx+channels.loopMode]
- cmp _ax,sdLoopNone
- je @@noloop
- cmp _ax,sdLoopAmigaNone
- je @@noloop
- cmp _ax,sdLoopAmiga
- je @@loopuni
-
- test [_bx+channels.status],gsReleased
- jnz @@loop2
-
- cmp [_bx+channels.loop1Type],loopUnidir
- je @@loopuni
- jmp @@loopbidi
-
- @@loop2:
- cmp [_bx+channels.loop2Type],loopNone
- je @@noloop
- cmp [_bx+channels.loop2Type],loopBidir
- je @@loopbidi
-
- @@loopuni:
- mov al,8
- jmp @@loopok
-
- @@loopbidi:
- mov al,24
- jmp @@loopok
-
- @@noloop:
- xor al,al
-
- @@loopok:
- out dx,al
- sti
-
- @@off: add _bx,SIZE gusChannel
- inc _cx
- cmp _cx,32
- jne @@chloop
- jmp @@done
-
- @@pause:
- xor _cx,_cx
- xor _bx,_bx
- @@chloop2:
- cli
- mov _dx,[voicesel] ; Select voice
- mov _ax,_cx
- out dx,al
-
- regsel 80h
- add _dx,2
- in al,dx
- sti
-
- and _ax,1 ; Voice on / off
- xor al,1 ; To active high
- shl al,5 ; to bit 5
- and [_bx+channels.status],NOT gsOnOff
- or [_bx+channels.status],_ax
-
- cli
- regsel 0
- add _dx,2
- mov al,3
- out dx,al ; Stop
- sti
-
- add _bx,SIZE gusChannel
- inc _cx
- cmp _cx,32
- jne @@chloop2
-
- @@done: xor _ax,_ax
- ret
- ENDP
-
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int gusSetMasterVolume(uchar master)
- ;*
- ;* Description: Sets the master volume for the GUS
- ;*
- ;* Input: int master new master volume (0-64)
- ;*
- ;* Returns: MIDAS error code.
- ;*
- ;\***************************************************************************/
-
- PROC gusSetMasterVolume _funct master : _int
- USES _bx
-
- mov _ax,[master]
- cmp [mastervol],_ax
- je @@done ; Already at that value
- mov [mastervol],_ax
- mov [masterchanged],1
- @@done: xor _ax,_ax ; Can't fail
- ret
- ENDP
-
-
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int gusGetMasterVolume(uchar *masterVolume)
- ;*
- ;* Description: Sets the master volume for the GUS
- ;*
- ;* Input: int *masterVolume pointer to master volume (0-64)
- ;*
- ;* Returns: MIDAS error code. Master volume is written to *masterVolume.
- ;*
- ;\***************************************************************************/
-
- PROC gusGetMasterVolume _funct masterVolume : _ptr
- USES _bx
-
- mov _ax,[mastervol]
- LOADPTR es,_bx,[masterVolume]
- mov [_esbx],_ax
- xor _ax,_ax ; Can't fail
- ret
- ENDP
-
-
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int gusSetAmplification(unsigned amplification);
- ;*
- ;* Description: Sets amplification level - does nothing except stores the
- ;* value for gusGetAmplification().
- ;*
- ;* Input: unsigned amplification amplification level - 64 = normal
- ;*
- ;* Returns: MIDAS error code.
- ;*
- ;\***************************************************************************/
-
- PROC gusSetAmplification _funct amplification : _int
-
- mov _ax,[amplification]
- mov [gusAmp],_ax
- xor _ax,_ax ; Can't fail
- ret
- ENDP
-
-
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int gusGetAmplification(unsigned *amplification);
- ;*
- ;* Description: Gets amplification level.
- ;*
- ;* Input: unsigned *amplification pointer to amplification level
- ;*
- ;* Returns: MIDAS error code. Amplification level is written to
- ;* *amplification.
- ;*
- ;\***************************************************************************/
-
- PROC gusGetAmplification _funct amplification : _ptr
- USES _bx
-
- mov _ax,[gusAmp]
- LOADPTR es,_bx,[amplification]
- mov [_esbx],_ax
- xor _ax,_ax ; Can't fail
- ret
- ENDP
-
-
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int gusPlaySound(int chan, ulong freq)
- ;*
- ;* Description: Starts a sound with a frequency
- ;*
- ;* Input: int chan Channel number
- ;* ulong freq Playing frequency
- ;*
- ;* Returns: MIDAS error code.
- ;*
- ;\***************************************************************************/
- PROC gusPlaySound _funct chan : _int, freq : dword
- USES _si,_bx
- LOCAL fc : _int
-
- mov _bx,[chan]
- cmp [chancount],_bx
- jle @@errchan
-
- imul _bx,_bx,size gusChannel ; Get channel block
-
- mov eax,[freq]
- cmp [_bx+channels.frequency],eax
- je @@nochange
- mov [_bx+channels.frequency],eax
-
- shl eax,10
- xor edx,edx
- IFDEF __16__
- xor ecx,ecx
- ENDIF
- mov _cx,[mixfreq] ; GUS freq = frequency / mixing rate
- idiv ecx
- and al,0feh ; Bit 0 unused
- mov [_bx+channels.fc],_ax
- mov [fc],_ax
- or [_bx+channels.status],gsFC
-
- @@nochange:
- mov _dx,[_bx+channels.inst] ; Instrument number
- test _dx,_dx
- jz @@errinst ; No instrument?
- cmp [numInsts],_dx
- jb @@errinst
-
- dec _dx ; Table starts from 1
- imul _dx,_dx,SIZE gusInstrument
-
- LOADPTR es,_si,[Instruments]
- add _si,_dx
- cmp [_essi+gusInstrument.length],0
- je @@stop
-
- mov ecx,[_essi+gusInstrument.sample] ; Start address
- mov [_bx+channels.scurrent],ecx ; Tell start position to GUS
- and [_bx+channels.status],NOT (gsStop OR gsReleased)
- or [_bx+channels.status],gsRetrig
-
- mov [_bx+channels.onoff],1
-
- IFNDEF NOSTEREO
- cmp [mEnableSurround],0
- je @@quit
-
- mov _bx,[chan]
- add _bx,[chancount]
- imul _bx,_bx,size gusChannel ; Get channel block
-
- mov eax,[freq]
- cmp [_bx+channels.frequency],eax
- je @@nocha
- mov [_bx+channels.frequency],eax
-
- mov _ax,[fc]
- mov [_bx+channels.fc],_ax
- or [_bx+channels.status],gsFC
-
- @@nocha:
- mov ecx,[_essi+gusInstrument.surround] ; Start address
- test ecx,ecx
- jnz @@ok2
- mov ecx,[_essi+gusInstrument.sample] ; Start address
- @@ok2: mov [_bx+channels.scurrent],ecx ; Tell start position to GUS
- and [_bx+channels.status],NOT (gsStop OR gsReleased)
- or [_bx+channels.status],gsRetrig
- mov [_bx+channels.onoff],1
- ENDIF
- @@quit:
- xor _ax,_ax
- ret
-
- @@stop: call gusStopSound LANG, [chan]
- ret
-
- @@errchan:
- mov _ax,errInvalidChanNumber
- jmp @@err
- @@errinst:
- mov _ax,errInvalidSampleHandle
- @@err: ERROR ID_gusPlaySound
- ret
-
- ENDP
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int gusReleaseSound(int chan)
- ;*
- ;* Description: Releases a sound in channel
- ;*
- ;* Input: int chan Channel number
- ;*
- ;* Returns: MIDAS error code.
- ;*
- ;\***************************************************************************/
-
- PROC gusReleaseSound _funct chan : _int
- USES _bx
-
- mov _bx,[chan]
- cmp [chancount],_bx
- jle @@errchan
-
- imul _bx,_bx,size gusChannel ; Get channel block
- or [_bx+channels.status],gsReleased
- xor _ax,_ax
- ret
-
- @@errchan:
- mov _ax,errInvalidChanNumber
- ERROR ID_gusReleaseSound
- ret
-
-
- ENDP
-
- ;/***************************************************************************\
- ;*
- ;* Function: int gusStopSound(int chan)
- ;*
- ;* Description: Stops sound on a channel
- ;*
- ;* Input: int chan Channel number
- ;*
- ;* Returns: MIDAS error code.
- ;*
- ;\***************************************************************************/
-
- PROC gusStopSound _funct chan : _int
- USES _bx
-
- mov _bx,[chan]
- cmp [chancount],_bx
- jle @@err
-
- imul _bx,_bx,size gusChannel ; Channel block
-
- and [_bx+channels.status],NOT gsRetrig
- or [_bx+channels.status],gsStop
-
- IFNDEF NOSTEREO
- cmp [mEnableSurround],0
- je @@quit
-
- mov _bx,[chan]
- add _bx,[chancount]
- imul _bx,_bx,size gusChannel ; Channel block
-
- and [_bx+channels.status],NOT gsRetrig
- or [_bx+channels.status],gsStop
- ENDIF
- @@quit: xor _ax,_ax
- ret
-
- @@err: mov _ax,errInvalidChanNumber
- ERROR ID_gusStopSound
- ret
- ENDP
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int gusSetRate(int chan, ulong freq)
- ;*
- ;* Description: Sets the playing rate for a channel
- ;*
- ;* Input: int chan Channel number
- ;* ulong freq New playing frequency
- ;*
- ;* Returns: MIDAS error code.
- ;*
- ;\***************************************************************************/
-
- PROC gusSetRate _funct chan : _int, freq : dword
- USES _bx
-
- mov _bx,[chan]
- cmp [chancount],_bx
- jle @@err
-
- imul _bx,_bx,size gusChannel
-
- mov eax,[freq]
- cmp [_bx+channels.frequency],eax
- je @@quit
- mov [_bx+channels.frequency],eax
-
- shl eax,10
- xor edx,edx
- IFDEF __16__
- xor ecx,ecx
- ENDIF
- mov _cx,[mixfreq] ; GUS freq = frequency / mixing rate
- idiv ecx
- and al,0feh ; bit 0 unused
- mov [_bx+channels.fc],_ax
- or [_bx+channels.status],gsFC
-
- IFNDEF NOSTEREO
- cmp [mEnableSurround],0
- je @@quit
-
- mov _bx,[chan]
- add _bx,[chancount]
- imul _bx,_bx,size gusChannel
-
- mov [_bx+channels.fc],_ax
- mov eax,[freq]
- mov [_bx+channels.frequency],eax
- or [_bx+channels.status],gsFC
- ENDIF
- @@quit: xor _ax,_ax
- ret
-
- @@err: mov _ax,errInvalidChanNumber
- ERROR ID_gusSetRate
- ret
- ENDP
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int gusGetRate(int chan, ulong *freq)
- ;*
- ;* Description: Returns the playing rate for a channel
- ;*
- ;* Input: int chan Channel number
- ;* ulong *freq Pointer to frequency
- ;*
- ;* Returns: MIDAS error code.
- ;*
- ;\***************************************************************************/
-
- PROC gusGetRate _funct chan : _int, freq : _ptr
- USES _bx
-
- mov _bx,[chan]
- cmp [chancount],_bx
- jle @@err
-
- cli
- mov _dx,[voicesel] ; Select voice
- mov _ax,_bx
- out dx,al
-
- regsel 80h ; Voice control
- add _dx,2
- in al,dx
- sti
-
- test al,1
- jnz @@stopped ; Is sound on?
-
- mov _bx,[chan]
- imul _bx,_bx,size gusChannel
-
- mov eax,[_bx+channels.frequency]
- LOADPTR es,_bx,[freq]
- mov [_esbx],eax
- xor _ax,_ax
- ret
-
- @@stopped:
- LOADPTR es,_bx,[freq]
- mov [dword _esbx],0
- xor _ax,_ax
- ret
-
- @@err: mov _ax,errInvalidChanNumber
- ERROR ID_gusGetRate
- ret
- ENDP
-
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int gusSetVolume(int chan, int volume)
- ;*
- ;* Description: Sets the volume for a channel
- ;*
- ;* Input: int chan Channel number
- ;* int volume New playing volume
- ;*
- ;* Returns: MIDAS error code.
- ;*
- ;\***************************************************************************/
- PROC gusSetVolume _funct chan : _int, vol : _int
- USES _bx
-
- mov _ax,[vol]
- cmp _ax,64
- jbe @@not64 ; Max volume = 64
- mov _ax,64
- @@not64:
- mov _bx,[chan]
- cmp [chancount],_bx
- jle @@err
-
- imul _bx,_bx,size gusChannel
-
- cmp [_bx+channels.volume],_ax
- je @@quit
-
- mov [_bx+channels.volume],_ax
- or [_bx+channels.status],gsVolume
-
- IFNDEF NOSTEREO
- cmp [mEnableSurround],0
- je @@quit
-
- mov _bx,[chan]
- add _bx,[chancount]
- imul _bx,_bx,size gusChannel
-
- mov [_bx+channels.volume],_ax
- or [_bx+channels.status],gsVolume
- ENDIF
- @@quit: xor _ax,_ax
- ret
-
- @@err: mov _ax,errInvalidChanNumber
- ERROR ID_gusSetVolume
- ret
-
- ENDP
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int gusGetVolume(int chan, int *volume)
- ;*
- ;* Description: Sets the volume for a channel
- ;*
- ;* Input: int chan Channel number
- ;* int *volume Pointer to volume
- ;*
- ;* Returns: MIDAS error code. Playing volume is written to *volume
- ;*
- ;\***************************************************************************/
-
- PROC gusGetVolume _funct chan : _int, volume : _ptr
- USES _bx
-
- mov _bx,[chan]
- cmp [chancount],_bx
- jle @@err
-
- imul _bx,_bx,size gusChannel
-
- mov _ax,[_bx+channels.volume]
- LOADPTR es,_bx,[volume]
- mov [_esbx],_ax
-
- xor _ax,_ax
- jmp @@done
-
- @@err: mov _ax,errInvalidChanNumber
- ERROR ID_gusGetVolume
-
- @@done:
- ret
-
- ENDP
-
-
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int gusSetSample(int chan, int sample)
- ;*
- ;* Description: Sets up a sample for playing
- ;*
- ;* Input: int chan Channel number
- ;* int inst Sample number from AddSample
- ;*
- ;* Returns: MIDAS error code.
- ;*
- ;\***************************************************************************/
-
- PROC gusSetSample _funct chan : _int, inst : _int
- USES edi,_si,_bx
-
- mov _bx,[chan]
- cmp [chancount],_bx
- jle @@errchn
- imul _bx,_bx,size gusChannel ; Channel block
-
- mov _ax,[inst]
- test _ax,_ax
- jz @@errinst ; No instrument at all?
- cmp [numInsts],_ax
- jb @@errinst
-
- mov _dx,_ax
- dec _dx ; Table starts from 1
- imul _dx,_dx,SIZE gusInstrument
- LOADPTR es,_si,[Instruments]
- add _si,_dx
-
- cmp [_bx+channels.inst],_ax
- je @@nochange
-
- mov [_bx+channels.inst],_ax ; Set instrument
-
- cmp [_essi+gusInstrument.length],0
- je @@stop
-
- mov _cx,[_essi+gusInstrument.sampleType]
- mov [_bx+channels.sampleType],_cx
-
- mov ecx,[_essi+gusInstrument.sample] ; Start address
- mov [_bx+channels.scurrent],ecx
- mov edi,ecx
-
- mov _dx,[_essi+gusInstrument.loop1Type]
- mov [_bx+channels.loop1Type],_dx ; Copy loop 1 type
- mov _dx,[_essi+gusInstrument.loop2Type]
- mov [_bx+channels.loop2Type],_dx ; Copy loop 2 type
-
- mov _dx,[_essi+gusInstrument.loopMode]
- mov [_bx+channels.loopMode],_dx ; Copy loop mode
-
- cmp _dx,sdLoopNone
- je @@noloop
- cmp _dx,sdLoopAmigaNone
- je @@noloop
-
- IFDEF __16__
- xor eax,eax
- ENDIF
- push ecx edi
- mov _ax,[_essi+gusInstrument.loop2End]
- add ecx,eax ; Loop 2 end address
- mov [_bx+channels.l2end],ecx
- mov _ax,[_essi+gusInstrument.loop2Start]
- add edi,eax ; Loop 2 end address
- mov [_bx+channels.l2start],edi
- pop edi ecx
-
- mov _ax,[_essi+gusInstrument.loop1End]
- add edi,eax ; Loop end address
- mov _ax,[_essi+gusInstrument.loop1Start]
- add ecx,eax ; Loop start address
- jmp @@duu
-
- @@noloop:
- IFDEF __16__
- xor eax,eax
- ENDIF
- mov _ax,[_essi+gusInstrument.length]
- add edi,eax ; Sample end address
- @@duu:
- mov [_bx+channels.sstart],ecx ; Tell loop start to GUS
- mov [_bx+channels.send],edi ; And loop end
- or [_bx+channels.status],gsSample
-
- @@nochange:
- IFNDEF NOSTEREO
- cmp [mEnableSurround],0
- je @@quit
-
- mov _bx,[chan]
- add _bx,[chancount]
- imul _bx,_bx,size gusChannel ; Channel block
-
- mov _ax,[inst]
-
- cmp [_bx+channels.inst],_ax
- je @@nochange2
-
- mov [_bx+channels.inst],_ax ; Set instrument
-
- mov ecx,[_essi+gusInstrument.surround] ; Start address
- test ecx,ecx
- jnz @@ok2
- mov ecx,[_essi+gusInstrument.sample] ; Start address
- @@ok2:
- mov edi,ecx
- IFDEF __16__
- xor eax,eax
- ENDIF
- mov _dx,[_essi+gusInstrument.loopMode]
- mov [_bx+channels.loopMode],_dx ; Copy loop mode
-
- cmp _dx,sdLoopNone
- je @@noloop2
- cmp _dx,sdLoopAmigaNone
- je @@noloop2
-
- mov _ax,[_essi+gusInstrument.loop1End]
- add edi,eax ; Loop end address
- mov _ax,[_essi+gusInstrument.loop1Start]
- add ecx,eax ; Loop start address
- jmp @@duu2
-
- @@noloop2:
- mov _ax,[_essi+gusInstrument.length]
- add edi,eax ; Sample end address
- @@duu2:
- mov [_bx+channels.sstart],ecx ; Tell loop start to GUS
- mov [_bx+channels.send],edi ; And loop end
- or [_bx+channels.status],gsSample
-
- @@nochange2:
- ENDIF
- @@quit:
- xor _ax,_ax
- ret
-
- @@stop: call gusStopSound LANG, [chan]
- ret
-
- @@errinst:
- mov _ax,errInvalidSampleHandle
- jmp @@err
- @@errchn:
- mov _ax,errInvalidChanNumber
- @@err: ERROR ID_gusSetSample
- ret
- ENDP
-
-
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int gusGetSample(int chan, ushort *sample)
- ;*
- ;* Description: Gets the last sample set for playing
- ;*
- ;* Input: int chan channel number
- ;* int *sample pointer to sample number
- ;*
- ;* Returns: MIDAS error code. Sample number is written to *sample.
- ;*
- ;\***************************************************************************/
-
- PROC gusGetSample _funct chan : _int, inst : _ptr
- USES _bx
-
- mov _bx,[chan]
- cmp [chancount],_bx
- jle @@errchn
- imul _bx,_bx,size gusChannel ; Channel block
-
- mov _ax,[_bx+channels.inst]
- LOADPTR es,_bx,[inst]
- mov [_esbx],_ax
-
- xor _ax,_ax
- jmp @@done
-
- @@errchn:
- mov _ax,errInvalidChanNumber
- ERROR ID_gusGetSample
-
- @@done:
- ret
- ENDP
-
-
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int gusSetPosition(int chan, ushort pos)
- ;*
- ;* Description: Sets the playing position for a channel
- ;*
- ;* Input: int chan Channel number
- ;* int pos New playing position
- ;*
- ;* Returns: MIDAS error code.
- ;*
- ;\***************************************************************************/
- PROC gusSetPosition _funct chan : _int, pos : _int
- USES _si,_bx
-
- mov _bx,[chan]
- cmp [chancount],_bx
- jle @@err
- imul _bx,_bx,size gusChannel ; Channel block
-
- mov _dx,[_bx+channels.inst]
- test _dx,_dx
- jz @@quit ; No instrument?
-
- dec _dx ; Table starts from 1
- imul _dx,_dx,SIZE gusInstrument
- LOADPTR es,_si,[Instruments]
- add _si,_dx
-
- IFDEF __16__
- xor ecx,ecx
- ENDIF
- mov _cx,[pos]
- cmp [_essi+gusInstrument.sampleType],smp16bit
- jne @@skip
- add _cx,_cx
- @@skip: cmp [_essi+gusInstrument.length],_cx ; Over from end?
- jae @@ok
-
- cmp [_essi+gusInstrument.loopMode],sdLoopAmiga
- je @@ale
-
- call gusStopSound LANG, [chan]
- ret
-
- @@ale: mov _cx,[_essi+gusInstrument.loop1Start] ; Yep. Start from loop
-
- @@ok: add ecx,[_essi+gusInstrument.sample] ; Add sample start to position
- mov [_bx+channels.scurrent],ecx ; Set start position
- and [_bx+channels.status],NOT gsStop
- or [_bx+channels.status],gsRetrig
- mov [_bx+channels.onoff],1
-
- IFNDEF NOSTEREO
- cmp [mEnableSurround],0
- je @@quit
-
- mov _bx,[chan]
- add _bx,[chancount]
- imul _bx,_bx,size gusChannel ; Channel block
- IFDEF __16__
- xor ecx,ecx
- ENDIF
- mov _cx,[pos]
- cmp [_essi+gusInstrument.surround],0
- je @@nop
- add ecx,[_essi+gusInstrument.surround] ; Add sample start to position
- jmp @@kop
- @@nop: add ecx,[_essi+gusInstrument.surround] ; Add sample start to position
- @@kop: mov [_bx+channels.scurrent],ecx ; Set start position
- and [_bx+channels.status],NOT gsStop
- or [_bx+channels.status],gsRetrig
- mov [_bx+channels.onoff],1
- ENDIF
- @@quit: xor _ax,_ax
- ret
-
- @@err: mov _ax,errInvalidChanNumber
- ERROR ID_gusSetPosition
- ret
- ENDP
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int gusGetPosition(int chan, ushort *pos)
- ;*
- ;* Description: Gets the playing position of a channel
- ;*
- ;* Input: int chan Channel number
- ;*
- ;* Returns: MIDAS error code.
- ;*
- ;\***************************************************************************/
-
- PROC gusGetPosition _funct chan : _int, pos:_ptr
- USES _si,_bx
-
- mov _bx,[chan]
- cmp [chancount],_bx
- jle @@err
-
- cli
- mov _dx,[voicesel] ; Select voice
- mov _ax,_bx
- out dx,al
-
- regsel 80h ; Voice control
- add _dx,2
- in al,dx
- test al,1
- jnz @@stopped ; Is sound on?
-
- imul _bx,_bx,size gusChannel ; Channel block
-
- ;FIXME!
- cmp [_bx+channels.sampleType],smp16bit
- je @@stopped
-
- @@huuko:
- regsel 8ah ; Current position high
- inc _dx
- in ax,dx
- IFDEF __16__
- xor ecx,ecx
- ENDIF
- mov _cx,_ax
- and _cx,01fffh
- shl ecx,7
-
- regsel 8bh ; Current position low
- inc _dx
- in ax,dx
- shr ax,9
- or _cx,_ax
-
- call gusdelay
-
- ; Read the value again to avoid GF1 self-modifying...
- regsel 8ah ; Current position high
- inc _dx
- in ax,dx
- IFDEF __16__
- xor esi,esi
- ENDIF
- mov _si,_ax
- and _si,01fffh
- shl esi,7
-
- regsel 8bh ; Current position low
- inc dx
- in ax,dx
- shr ax,9
- or _si,_ax
-
- ; Some sanity checking...
- sub esi,ecx
- js @@huuko
- cmp esi,16
- ja @@huuko
-
- mov _bx,[_bx+channels.curinst]
- dec _bx
- imul _bx,_bx,SIZE gusInstrument
-
- LOADPTR es,_si,[Instruments]
- sub ecx,[_essi+_bx+gusInstrument.sample]
- jns @@oke2
-
- xor ecx,ecx
- jmp @@oke
- @@oke2:
- cmp ecx,[_essi+_bx+gusInstrument.length]
- jb @@oke
-
- mov ecx,[_essi+_bx+gusInstrument.length]
- dec ecx
-
- @@oke: sti
- LOADPTR es,_bx,[pos]
- mov [_esbx],_cx
- xor _ax,_ax
- ret
-
- @@stopped: ; No sound is being played
- xor _cx,_cx
- jmp @@oke
- ret
-
- @@err: mov _ax,errInvalidChanNumber
- ERROR ID_gusGetPosition
- ret
-
- ENDP
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int gusGetDirection(int chan, ushort *dir)
- ;*
- ;* Description: Gets the playing direction of a channel
- ;*
- ;* Input: int chan Channel number
- ;* int dir Pointer to direction
- ;*
- ;* Returns: MIDAS error code.
- ;* Playing direction is stored in *dir.
- ;*
- ;\***************************************************************************/
-
- PROC gusGetDirection _funct chan : _int, dir : _ptr
- USES _bx
-
- mov _ax,[chan]
- cmp [chancount],_ax
- jle @@err
-
- cli
- mov _dx,[voicesel] ; Select voice
- out dx,al
-
- regsel 80h ; Voice control
- add _dx,2
- in al,dx
- sti
-
- test al,40h
- jnz @@back
- mov _ax,1
- jmp @@end
- @@back:
- mov _ax,-1
- @@end: LOADPTR es,_bx,[pos]
- mov [_esbx],_ax
- xor _ax,_ax
- ret
-
- @@err: mov _ax,errInvalidChanNumber
- ERROR ID_gusGetDirection
- ret
- ENDP
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int gusSetPanning(int chan, int panning)
- ;*
- ;* Description: Sets the panning position for a channel
- ;*
- ;* Input: int channel Channel number
- ;* int panning Panning value (See enum)
- ;*
- ;* Returns: MIDAS error code.
- ;*
- ;\***************************************************************************/
-
- PROC gusSetPanning _funct chan : _int, panning : _int
- USES _bx
-
- mov _ax,[chan]
- cmp [chancount],_ax
- jle @@err
- mov _dx,[voicesel] ; Voice Select
- out dx,al
-
- mov _bx,_ax
- imul _bx,_bx,size gusChannel ; Channel block
-
- mov _ax,[panning]
- cmp [_bx+channels.panning],_ax
- je @@kwit
- mov [_bx+channels.panning],_ax ; Panning position
-
- IFNDEF NOSTEREO
- cmp [monoFlag],1
- je @@kwit ; Skip if forced mono
-
- cmp _ax,panSurround
- jne @@juuh
-
- cmp [mEnableSurround],0
- jne @@huu
- xor _ax,_ax ; No surround enabled --> middle
- jmp @@juuh
-
- @@huu:
- mov [_bx+channels.panningHW],0 ; Extreme left
- or [_bx+channels.status],gsPanning
-
- mov [_bx+channels.surround],1 ; This is a surround channel
- mov _ax,[_bx+channels.status] ; Copy status (mute)
-
- mov _cx,[chancount]
- imul _cx,_cx,size gusChannel ; Channel block
- add _bx,_cx
-
- mov [_bx+channels.panningHW],15 ; Extreme right
- mov [_bx+channels.surround],1 ; This is a surround, too
- mov [_bx+channels.status],_ax
- jmp @@jatkuu
-
- @@juuh: mov [_bx+channels.surround],0 ; Normal channel
-
- sar _ax,3
- or _ax,_ax ; Sign
- jns @@pos
- inc _ax
- @@pos: add _ax,7
- mov [_bx+channels.panningHW],_ax
- or [_bx+channels.status],gsPanning
-
- mov _bx,[chan]
- add _bx,[chancount]
- cmp _bx,32
- jae @@jatkuu
- imul _bx,_bx,size gusChannel ; Channel block
- mov [_bx+channels.surround],0 ; No longer surround channel (?)
- or [_bx+channels.status],gsMute
-
- @@jatkuu:
- mov [masterchanged],1 ; Force reset of volume
- ENDIF
- @@kwit: sti
- @@quit: xor _ax,_ax
- ret
-
- @@err: mov _ax,errInvalidChanNumber
- ERROR ID_gusSetPanning
- ret
- ENDP
-
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int gusGetPanning(int chan, short *panning)
- ;*
- ;* Description: Gets the panning position for a channel
- ;*
- ;* Input: int channel Channel number
- ;* int *panning Pointer to panning value
- ;*
- ;* Returns: MIDAS error code.
- ;* Panning value is stored in *panning.
- ;*
- ;\***************************************************************************/
-
- PROC gusGetPanning _funct channel : _int, panning : _ptr
- USES _bx
-
- mov _bx,[channel]
- cmp [chancount],_bx
- jle @@err
- imul _bx,_bx,size gusChannel ; Channel block
- mov _ax,[_bx+channels.panning] ; Panning position
- LOADPTR es,_bx,[panning]
- mov [_esbx],_ax
- xor _ax,_ax
- ret
-
- @@err: mov _ax,errInvalidChanNumber
- ERROR ID_gusGetPanning
- ret
- ENDP
-
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int gusMuteChannel(int chan, int mute)
- ;*
- ;* Description: Mutes or unmutes a channel
- ;*
- ;* Input: int chan Channel number
- ;* int mute Unmute = 0 / Mute = 1
- ;*
- ;* Returns: MIDAS error code.
- ;*
- ;\***************************************************************************/
-
- PROC gusMuteChannel _funct chan : _int, mute : _int
- USES _bx
-
- mov _bx,[chan]
- cmp [chancount],_bx
- jle @@err
- imul _bx,_bx,SIZE gusChannel
-
- cmp [mute],1
- je @@mute
- and [_bx+channels.status],NOT gsMute
- or [_bx+channels.status],gsVolume
- jmp @@guu
- @@mute:
- or [_bx+channels.status],gsMute OR gsVolume
-
- @@guu:
- IFNDEF NOSTEREO
- cmp [_bx+channels.surround],0
- je @@pois
-
- mov _bx,[chan]
- add _bx,[chancount]
- imul _bx,_bx,SIZE gusChannel
-
- cmp [mute],1
- je @@mute2
- and [_bx+channels.status],NOT gsMute
- or [_bx+channels.status],gsVolume
- jmp @@pois
- @@mute2:
- or [_bx+channels.status],gsMute OR gsVolume
- ENDIF
- @@pois: xor _ax,_ax
- ret
-
- @@err: mov _ax,errInvalidChanNumber
- ERROR ID_gusMuteChannel
- ret
-
- ENDP
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int gusAddSample(sdSample *sample, int copySample,
- ;* int *sdNum);
- ;*
- ;* Description: Adds a new sample to the sample list
- ;*
- ;* Input: sdSample *sample pointer to sample information
- ;* structure.
- ;* int copySample 1 if sample should be copied
- ;* int *sdNum pointer to variable to store the SD
- ;* sample handle
- ;*
- ;* Returns: MIDAS error code.
- ;* SD sample handle is stored in *sdNum.
- ;*
- ;\***************************************************************************/
-
- PROC gusAddSample _funct sample : _ptr, copysample : _int, sdNum : _ptr
- USES _si,_di,_bx
- LOCAL gusmem : dword, gusmem2 : dword, smpStart : _ptr, glength : _int, \
- loopMode : _int, loopStart : _int
-
- LOADPTR gs,_si,[sample]
- cmp [_gssi+sdSample.sampleType],smp8bit
- je @@instok
- cmp [_gssi+sdSample.sampleType],smp16bit
- je @@instok
- cmp [_gssi+sdSample.sampleType],smpNone
- jne @@errinst
- mov [_gssi+sdSample.sampleLength],0
- @@instok:
- mov _ax,[instpos]
- dec _ax ; Table starts from 1
- imul _ax,_ax,SIZE gusInstrument
- LOADPTR es,_di,[Instruments]
- add _di,_ax
-
- cmp [_gssi+sdSample.sampleLength],0
- je @@nsurr
-
- cmp [_gssi+sdSample.sampleType],smp8bit
- jne @@not8bit
-
- ; FIXME!!!!
- mov _cx,[_gssi+sdSample.sampleLength]
-
- PUSHSEGREG es
- LOADPTR es,_bx,[_gssi+sdSample.sample] ; Pointer to sample
- @@signloop:
- xor [byte _esbx],80h
- inc _bx
- dec _cx
- jnz @@signloop
- POPSEGREG es
-
- @@not8bit:
- PUSHSEGREG es gs
- call gusMalloc LANG, [_gssi+sdSample.sampleLength], \
- [_gssi+sdSample.sampleType], ptr_to temp
- POPSEGREG gs es
- test _ax,_ax
- jnz @@err
-
- mov eax,[temp]
- mov [gusmem],eax
-
- mov [_esdi+gusInstrument.sample],eax ; Sample start
- mov [_esdi+gusInstrument.surround],0
-
- IFNDEF NOSTEREO
- cmp [mEnableSurround],0
- je @@nsurr
- cmp [_gssi+sdSample.sampleType],smp16bit
- je @@nsurr
-
- PUSHSEGREG es
- call gusMalloc LANG, [_gssi+sdSample.sampleLength], \
- [_gssi+sdSample.sampleType], ptr_to temp
- POPSEGREG es
- test _ax,_ax
- jnz @@err
-
- mov eax,[temp]
- mov [gusmem2],eax
- mov [_esdi+gusInstrument.surround],eax ; Surround sample start
- ENDIF
- @@nsurr:
- COPYPTR [smpStart],[_gssi+sdSample.sample]
-
- ; FIXME!
- mov _ax,[_gssi+sdSample.sampleType]
- cmp _ax,smpNone
- jne @@smp2
- mov _ax,smp8bit
- @@smp2:
- mov [_esdi+gusInstrument.sampleType],_ax
-
- mov _ax,[_gssi+sdSample.sampleLength]
- mov [_esdi+gusInstrument.length],_ax ; Sample length
-
- mov _ax,[_gssi+sdSample.loopMode]
- mov [_esdi+gusInstrument.loopMode],_ax
- mov [loopMode],_ax
-
- mov _ax,[_gssi+sdSample.loop1Type]
- mov [_esdi+gusInstrument.loop1Type],_ax
-
- mov _ax,[_gssi+sdSample.loop1Start]
- mov [_esdi+gusInstrument.loop1Start],_ax
-
- mov _ax,[_gssi+sdSample.loop1End]
- mov [_esdi+gusInstrument.loop1End],_ax
-
- mov _ax,[_gssi+sdSample.loop2Type]
- mov [_esdi+gusInstrument.loop2Type],_ax
-
- mov _ax,[_gssi+sdSample.loop2Start]
- mov [_esdi+gusInstrument.loop2Start],_ax
-
- mov _ax,[_gssi+sdSample.loop2End]
- mov [_esdi+gusInstrument.loop2End],_ax
-
- ;PK-
- cmp [loopMode],sdLoop2
- jne @@loop1
- ;-PK
- cmp [_gssi+sdSample.loop2Type],loopNone
- je @@loop1
- mov _ax,[_gssi+sdSample.loop2Start]
- jmp @@loopok
- @@loop1:
- mov _ax,[_gssi+sdSample.loop1Start]
- @@loopok:
- mov [loopStart],_ax
-
- mov _cx,[_gssi+sdSample.sampleLength]
- test _cx,_cx
- jz @@qwit
-
- LOADPTR es,_si,[smpStart] ; Pointer to sample
-
- mov ebx,[gusmem] ; Start in GUS memory
- IFDEF __32__
- xor edi,edi
- ENDIF
- mov di,bx
- shr ebx,16
-
- mov [flag],1
-
- @@dumploop2:
- cli
- regsel 44h ; Addr hi
- add _dx,2 ; 3x5
- mov _ax,_bx
- out dx,al ; upper bits of address
- sti
-
- regsel 43h ; Addr lo
- @@dumploop:
- mov _dx,[selreg]
- mov _ax,_di
- inc _dx ; 3x4
- out dx,ax
- add _dx,3 ; 3x7
- mov al,[_essi] ; Get data
- inc _si
- out dx,al
-
- inc di
- jz @@yli64
- dec _cx
- jnz @@dumploop ; Dump the whole sample
- jmp @@quit
-
- @@yli64:
- inc _bx ; Crossed 64kb border
- dec _cx
- jnz @@dumploop2 ; Dump the whole sample
-
-
- @@quit:
- cmp [loopMode],sdLoopNone
- je @@noloob
- cmp [loopMode],sdLoop1Rel
- je @@noloob
- cmp [loopMode],sdLoopAmigaNone
- je @@noloob
- @@loobed: ; Copy loop to next 32 byte border
- LOADPTR es,_si,[smpStart]
- add _si,[loopStart]
-
- mov _dx,_di
- mov _cx,64
- and _dx,01fh ; AND lowest bits off
- sub _cx,_dx
-
- @@dumploop3:
- cli
- regsel 44h ; Addr hi
- add _dx,2 ; 3x5
- mov _ax,_bx
- out dx,al ; upper bits of address
- sti
-
- regsel 43h ; Addr lo
- @@dumploop4:
- mov _dx,[selreg]
- mov _ax,_di
- inc _dx ; 3x4
-
- out dx,ax
- add _dx,3 ; 3x7
- mov al,[_essi] ; Get data
- inc _si
- out dx,al
-
- inc di
- jz @@yli642
- dec _cx
- jnz @@dumploop4 ; Do whole loop
- jmp @@qwti
-
- @@yli642:
- inc _bx ; Crossed 64kb border
- dec _cx
- jnz @@dumploop3 ; Do whole loop
- jmp @@qwti
-
-
- @@noloob: ; Copy the last byte
- dec _si
- mov _dx,_di
- mov _cx,64
- and _dx,01fh ; AND lowest bits away...
- sub _cx,_dx
-
- @@dumploop5:
- cli
- regsel 44h ; addr hi
- add _dx,2 ; 3x5
- mov _ax,_bx
- out dx,al ; upper bits of address
- sti
-
- regsel 43h ; addr lo
- @@dumploop6:
- mov _dx,[selreg]
- inc _dx ; 3x4
- mov _ax,_di
-
- out dx,ax
- mov al,[_essi] ; Get data
- add _dx,3 ; 3x7
- out dx,al
-
- inc di
- jz @@yli643
- dec _cx
- jnz @@dumploop6
- jmp @@qwti
-
- @@yli643:
- inc _bx ; Crossed 64kb border
- dec _cx
- jnz @@dumploop5
-
- @@qwti:
- LOADPTR gs,_si,[sample]
-
- IFNDEF NOSTEREO
- cmp [mEnableSurround],0
- je @@qwit
- cmp [_gssi+sdSample.sampleType],smp16bit
- je @@qwit
-
- call CopySurroundSample LANG, [smpStart], [glength], [loopStart],\
- [loopMode], [gusmem2]
-
- ENDIF
- @@qwit:
- cmp [_gssi+sdSample.sampleType],smp8bit
- jne @@not8bit2
-
- ; FIXME!!!!
- mov _cx,[_gssi+sdSample.sampleLength]
- test _cx,_cx
- jz @@not8bit2
-
- PUSHSEGREG es
- LOADPTR es,_bx,[_gssi+sdSample.sample] ; Pointer to sample
- @@signloop2:
- xor [byte _esbx],80h
- inc _bx
- dec _cx
- jnz @@signloop2
- POPSEGREG es
-
- @@not8bit2:
- push [instpos] ; Return instrument number
-
- mov [flag],0
-
- mov _ax,[instpos]
- mov _bx,_ax
- dec _bx
- imul _bx,_bx,SIZE gusInstrument
- LOADPTR es,_si,[Instruments]
- add _si,_bx
- @@search: ; Search next free instrument
- cmp [_essi+gusInstrument.sampleType],smpNone
- je @@found
- add _si,SIZE gusInstrument
- inc _ax
- jmp @@search
-
- @@found:
- mov [instpos],_ax
- pop _ax
- LOADPTR es,_bx,[sdNum]
- mov [_esbx],_ax
-
- cmp [numInsts],_ax
- jae @@huu
- mov [numInsts],_ax
- @@huu:
- xor _ax,_ax
- ret
-
-
- @@errinst:
- mov _ax,errInvalidInst
- @@err: ERROR ID_gusAddSample
- ret
- ENDP
-
-
- IFNDEF NOSTEREO
- PROC CopySurroundSample NEAR inst : _ptr, glength : _int, loopStart : _int,\
- gloop : _int, gusmem : dword
- USES _si,_di,_bx
-
- LOADPTR es,_si,[inst] ; Pointer to sample
-
- mov _cx,[glength]
-
- mov ebx,[gusmem] ; Start in GUS memory
- mov _di,_bx
- shr ebx,16
-
- @@dumploop2:
- cli
- regsel 44h
- add _dx,2 ;3x5
- mov _ax,_bx
- out dx,al ;upper bits of address
- sti
-
- regsel 43h
- @@dumploop:
- mov _dx,[selreg]
- inc _dx ; 3x4
- mov _ax,_di
- out dx,ax
- add _dx,3 ; 3x7
- mov al,[_essi] ; Get data
- inc _si
- not al ; 180 degree phase transformation
- out dx,al
-
- inc di
- jz @@yli64
- dec _cx
- jnz @@dumploop ; Dump the whole sample
- jmp @@quit
-
- @@yli64:
- inc _bx ; Crossed 64kb border
- dec _cx
- jnz @@dumploop2 ; Dump the whole sample
-
- @@quit:
- cmp [loopMode],sdLoopNone
- je @@noloob
- cmp [loopMode],sdLoop1Rel
- je @@noloob
- cmp [loopMode],sdLoopAmigaNone
- je @@noloob
-
- @@loobed: ; Copy loop to next 32 byte border
- LOADPTR es,_si,[inst]
- add _si,[loopStart]
-
- mov _dx,_di
- and _dx,01fh ; AND the lowest bits away...
- mov _cx,64
- sub _cx,_dx
-
- @@dumploop3:
- cli
- regsel 44h
- add _dx,2 ;3x5
- mov _ax,_bx
- out dx,al ;upper bits of address
- sti
-
- regsel 43h
- @@dumploop4:
- mov _dx,[selreg]
- mov _ax,_di
- inc _dx ; 3x4
-
- out dx,ax
- add _dx,3 ; 3x7
- mov al,[_essi] ; Get data
- inc _si
- not al ; 180 degree phase transformation
- out dx,al
-
- inc di
- jz @@yli642
- dec _cx
- jnz @@dumploop4 ; Do whole loop
- jmp @@qwit
-
- @@yli642:
- inc _bx ; Crossed 64kb border
- dec _cx
- jnz @@dumploop3 ; Do whole loop
- jmp @@qwit
-
- @@noloob: ; Copy the last byte
- mov _dx,_di
- dec _si
- and _dx,01fh ; Alimmat pois
- mov _cx,64
- sub _cx,_dx
-
- @@dumploop5:
- cli
- regsel 44h
- add _dx,2 ;3x5
- mov _ax,_bx
- out dx,al ;upper bits of address
- sti
-
- regsel 43h
- @@dumploop6:
- mov _dx,[selreg]
- mov _ax,_di
- inc _dx ; 3x4
-
- out dx,ax
- add dx,3 ; 3x7
- mov al,[_essi] ; Get data
- not al ; 180 degree phase transformation
- out dx,al
-
- inc di
- jz @@yli643
- dec _cx
- jnz @@dumploop6
- jmp @@qwit
- @@yli643:
- inc _bx ; Crossed 64kb border
- dec _cx
- jnz @@dumploop5
- @@qwit:
- ret
- ENDP
- ENDIF
-
- ;/***************************************************************************\
- ;*
- ;* Function: int gusRemoveSample(int sample)
- ;*
- ;* Description: Removes a sample from the GUS SD internal tables
- ;* and frees it from GUS memory
- ;*
- ;* Input: int sample Sample number from AddSample
- ;*
- ;* Returns: MIDAS error code.
- ;*
- ;\***************************************************************************/
-
- PROC gusRemoveSample _funct sample : _int
- USES _si,_bx
-
- mov _bx,[inst]
- dec _bx
- imul _bx,_bx,SIZE gusInstrument
- LOADPTR es,_si,[Instruments]
- add _si,_bx
-
- cmp [_essi+gusInstrument.sampleType],smpNone
- je @@nothing
-
- mov [_essi+gusInstrument.sampleType],smpNone ; Free instrument
-
- cmp [_essi+gusInstrument.length],0
- je @@nsurround
-
- PUSHSEGREG es
- call gusFree LANG, [_essi+gusInstrument.sample]
- POPSEGREG es
- test _ax,_ax
- jnz @@err
-
- IFNDEF NOSTEREO
- cmp [_essi+gusInstrument.surround],0
- je @@nsurround
-
- call gusFree LANG, [_essi+gusInstrument.surround]
- test _ax,_ax
- jnz @@err
- ENDIF
- @@nsurround:
- mov _ax,[inst]
- cmp [instpos],_ax
- jbe @@nothing
-
- mov [instpos],_ax ; Lowest instrument number
- @@nothing:
- cmp [numInsts],_ax
- jne @@juu
-
- LOADPTR es,_si,[Instruments]
- mov _cx,_ax
- mov _bx,1
- mov _ax,_bx
- @@search: ; Search next free instrument
- cmp [_essi+gusInstrument.sampleType],smpNone
- je @@nop
- mov _ax,_bx
- @@nop: add _si,SIZE gusInstrument
- inc _bx
- dec _cx
- jnz @@search
- mov [numInsts],_ax
- @@juu: xor _ax,_ax
- ret
-
- @@err: ERROR ID_gusRemoveSample
- ret
- ENDP
-
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int gusSetUpdRate(int rate)
- ;*
- ;* Description: Sets the update rate of SD.
- ;*
- ;* Input: int rate Rate in Hz*100
- ;*
- ;* Returns: MIDAS error code.
- ;*
- ;\***************************************************************************/
-
- PROC gusSetUpdRate _funct rate : _int
-
- mov _ax,[rate]
- mov [updRate],_ax
- xor _ax,_ax
- ret
- ENDP
-
-
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int gusStartPlay(void);
- ;*
- ;* Description: Called before gusPlay() is called. This function doesn't
- ;* have to do anything, however.
- ;*
- ;* Returns: MIDAS error code
- ;*
- ;\***************************************************************************/
-
- PROC gusStartPlay _funct
-
- xor _ax,_ax
- ret
- ENDP
-
-
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int gusPlay(int *callMP)
- ;*
- ;* Description: Updates the GUS registers according to the Sound Device
- ;* internal datas
- ;*
- ;* Returns: MIDAS error code.
- ;*
- ;\***************************************************************************/
- PROC gusPlay _funct callMP : _ptr
- LOCAL chanc : _int, selsave : _int, voicesave : _int, retrigfl : _int
- USES _di,_si,_bx
-
- cmp [paused],0
- jne @@paused
-
- cmp [chansOpen],0
- je @@paused
-
- xor _ax,_ax
- mov _dx,[voicesel]
- in al,dx
- mov [voicesave],_ax
-
- mov _dx,[selreg]
- in al,dx
- cmp [flag],0 ; Are we uploading
- je @@kd ; at the same time?
- mov al,43h
- @@kd: mov [selsave],_ax
-
- mov [chanc],0 ; Start from channel 0
- xor _si,_si ; Channel data
- @@loop:
- cmp [_si+channels.onoff],0
- je @@retrigged
-
- mov _dx,[voicesel] ; Select voice
- mov _ax,[chanc]
- out dx,al
-
- test [_si+channels.status],gsStop OR gsRetrig ; Retrig / stop sound?
- jz @@nothing
-
- and [_si+channels.status],NOT gsStop
-
- IF FASTGUS
- test [_si+channels.status],gsRetrig
- jz @@juststop
-
- regsel 9 ; Current volume
- inc _dx
- mov _ax,1500h
- out dx,ax
-
- call gusdelay
-
- out dx,ax
- jmp @@setfc
-
- @@juststop:
- ENDIF
- regsel 7 ; Volume ramp start
- add _dx,2
- mov al,15h ; to zero
- out dx,al
-
- regsel 0dh ; Volume ramp control
- add _dx,2
- mov al,40h ; Start decreasing ramp
- out dx,al
-
- regsel 0 ; Voice control
- add _dx,2
- mov al,3 ; Stop voice
- out dx,al
-
- call gusdelay
-
- out dx,al ; again...
-
- regsel 0dh ; Volume ramp control
- add _dx,2
- mov al,40h ; Start decreasing ramp
- out dx,al
- jmp @@setfc
-
- @@nothing:
- cmp [masterchanged],0
- jnz @@set
- test [_si+channels.status],gsVolume
- jz @@setfc
- @@set: and [_si+channels.status],NOT gsVolume
- regsel 89h
- inc _dx
- in ax,dx
-
- mov cx,ax
- xor cl,cl
-
- mov _ax,[_si+channels.volume] ; To set volume
- test [_si+channels.status],gsMute
- jz @@oek2
- xor _ax,_ax
- @@oek2: mov _bx,[mastervol]
- mul bl
- shr _ax,6
- mov _bx,_ax
- add _bx,_bx
- mov bx,[voltable+_bx]
-
- cmp [_si+channels.surround],0
- je @@hu2
- sub bh,10h ; Halve the volume
- @@hu2: xor bl,bl
- cmp cx,bx
- je @@setfc ; Already at that value
- cmp cx,bx
- jb @@yli
- xchg cx,bx
- mov cl,40h
- @@yli:
- regsel 0dh ; Ramp Control
- add _dx,2
- mov al,3
- out dx,al ; Stop Ramp
-
- call gusdelay
-
- out dx,al ; Stop Ramp
-
- regsel 7 ; Ramp start
- add _dx,2
- mov al,ch ; From lower
- out dx,al
-
- regsel 8 ; Ramp end
- add _dx,2
- mov al,bh ; To higher volume
- out dx,al
-
- regsel 0dh ; Ramp Control
- add _dx,2
- mov al,cl
- out dx,al ; GO!
-
- call gusdelay
-
- out dx,al ; GO!
-
- @@setfc:
- test [_si+channels.status],gsFC
- jz @@setpan
-
- and [_si+channels.status],NOT gsFC
- regsel 1 ; Frequency control
- inc _dx
- @@writefc:
- mov _ax,[_si+channels.fc]
- out dx,ax
-
- ; Let's see if this helps the Tone Portamento problems... (PK)
- ; Unfortunately this has no chances of working, reading GUS
- ; registers is made from register+80h... (JP)
- if 0
- call gusdelay
- in ax,dx
- cmp _ax,[_si+channels.fc]
- je @@fcok
- call gusdelay
- jmp @@writefc
- @@fcok:
- ; End of TP fix
- endif
-
-
- @@setpan:
- test [_si+channels.status],gsPanning
- jz @@stopped
-
- and [_si+channels.status],NOT gsPanning
-
- cmp [GUS.cardType], gusIW
- jz @@iwsmoothpan ; no crappy on/off panning for iw ;)
- ; regular gus compatible panning
- regsel 12 ; Pan Position
- add _dx,2
- mov _ax,[_si+channels.panningHW]
- out dx,al
- jmp @@stopped
- @@iwsmoothpan:
- mov _bx, [_si+channels.panning]
- add _bx, _bx
- ;interwave synth right offset ( bigger blocks sound )
- regsel 0ch
- inc dl
- mov ax, [pantablemid+_bx]
- out dx, ax
- regsel 1bh ; right offset fine
- inc dl
- mov ax, [pantablemid+_bx]
- out dx, ax
-
- neg _bx
- ;interwave synth left offset
- regsel 13h ; left offset
- inc dl
- mov ax, [pantablemid+_bx]
- out dx, ax
- regsel 1ch ; left offset fine
- inc dl
- mov ax, [pantablemid+_bx]
- out dx, ax
-
- @@stopped:
- test [_si+channels.status],gsSample
- jz @@retrigged ; No sample changed
-
- cmp [_si+channels.loopMode],sdLoopAmigaNone
- je @@ALE
- cmp [_si+channels.loopMode],sdLoopAmiga
- jne @@noALE
-
- @@ALE: test [_si+channels.status],gsRetrig
- jnz @@retrigged ; Already to be retrigged
-
- ; GUS-AMIGA-LOOP-EMULATOR (GALE) (TM) V1.14!!!
-
- regsel 80h ; Voice control
- add _dx,2
- in al,dx
-
- test al,1
- jz @@soundon
-
- cmp [_si+channels.loopMode],sdLoopAmigaNone ; Next sample looped?
- je @@stopsound ; No
-
- mov _ax,[_si+channels.inst]
- mov [_si+channels.curinst],_ax
-
- mov ebx,[_si+channels.sstart]
- jmp @@startfromloop ; Start from loop start
-
- @@soundon:
- mov eax,[_si+channels.frequency]
- imul eax,eax,100 ; updRate is Hz*100
- xor edx,edx
-
- IFDEF __16__
- xor ebx,ebx
- ENDIF
- mov _bx,[updRate]
- idiv ebx ; eax = bytes to play until next update
- push eax
-
- regsel 84h ; Sample end position high
- inc _dx
- in ax,dx
- IFDEF __16__
- xor ebx,ebx
- ENDIF
- mov _bx,_ax
- and _bx,01fffh
- shl ebx,7
-
- regsel 85h ; Sample end position low
- inc _dx
- in ax,dx
- shr ax,9
- or _bx,_ax
-
- regsel 8ah ; Current position high
- inc _dx
- in ax,dx
- IFDEF __16__
- xor ecx,ecx
- ENDIF
- mov _cx,_ax
- and _cx,01fffh
- shl ecx,7
-
- regsel 8bh ; Current position low
- inc _dx
- in ax,dx
- shr ax,9
- or _cx,_ax
-
- sub ebx,ecx ; Bytes to sample / loop end
- pop eax
-
- cmp ebx,eax
- jg @@retrigged ; Some sample still to go
-
- test [_si+channels.loopMode],sdLoopAmigaNone ; Looped?
- je @@stopsound
-
- mov _ax,[_si+channels.inst]
- mov [_si+channels.curinst],_ax
-
- cmp ebx,0
- jg @@norm
-
- mov ebx,[_si+channels.sstart]
- jmp @@startfromloop
-
- @@norm: mov ecx,[_si+channels.send]
- sub ecx,ebx
- mov ebx,ecx
-
- @@startfromloop:
- ; EBX = Starting position
-
- mov ecx,[_si+channels.send] ; Set sample end
-
- regsel 4 ; End position high
- inc _dx
- mov eax,ecx
- shr eax,7
- out dx,ax
- regsel 5 ; End position low
- inc _dx
- mov eax,ecx
- shl _ax,9
- out dx,ax
-
- mov ecx,[_si+channels.sstart] ; Set loop start
-
- regsel 2 ; Start position high
- inc _dx
- mov eax,ecx
- shr eax,7
- out dx,ax
- regsel 3 ; Start position low
- inc _dx
- mov eax,ecx
- shl _ax,9
- out dx,ax
-
- regsel 0 ; Voice control
- mov al,8 ; Enable voice and loop
- add _dx,2
- out dx,al
-
- regsel 10 ; Current position high
- inc _dx
- mov eax,ebx
- shr eax,7
- out dx,ax
- regsel 11 ; Current position low
- inc _dx
- mov eax,ebx
- shl _ax,9
- out dx,ax
-
- call gusdelay ; Delay
-
- out dx,ax
-
- regsel 10 ; Current position high
- inc _dx
- mov eax,ebx
- shr eax,7
- out dx,ax
-
- regsel 0 ; Voice control
- add _dx,2
- mov al,8 ; Enable voice and loop
- out dx,al
- jmp @@retrigged
-
- @@stopsound:
- regsel 0 ; Voice control
- add _dx,2
- mov al,3 ; Stop voice
- out dx,al
-
- regsel 9 ; Current volume
- inc _dx
- mov _ax,1500h ; To zero
- out dx,ax
-
- regsel 0dh ; Ramp control
- add _dx,2
- mov al,3 ; Stop
- out dx,al
-
- call gusdelay
-
- out dx,al
-
- regsel 0 ; Voice control
- add _dx,2
- mov al,3 ; Stop voice
- out dx,al
-
- regsel 9 ; Current volume
- inc _dx
- mov ax,1500h ; To zero
- out dx,ax
-
- @@noALE:
- @@retrigged:
- add _si,size gusChannel ; Do all channels in order
- inc [chanc]
- mov _ax,[chancount]
-
- IFNDEF NOSTEREO
- cmp [mEnableSurround],0
- je @@ij
- add _ax,_ax ; Plus Surround channels
- @@ij:
- ENDIF
- cmp [chanc],_ax
- jb @@loop
-
- @@waitloop:
- mov [chanc],0 ; Start from channel 0
- xor _si,_si ; Channel data
- mov [retrigfl],0
- @@loop2:
- cmp [_si+channels.onoff],0
- je @@skip
-
- test [_si+channels.status],gsRetrig ; Retrig?
- jz @@skip
-
- mov _dx,[voicesel] ; Select voice
- mov _ax,[chanc]
- out dx,al
-
- IFE FASTGUS
- regsel 8dh ; Ramp finished?
- add _dx,2
- in al,dx
- test al,1
- jnz @@retrig
-
- mov [retrigfl],1 ; Still voice(s) to wait...
- jmp @@skip
- ENDIF
- @@retrig:
- test [_si+channels.status],gsSample
- jz @@not ; No sample changed
-
- mov ecx,[_si+channels.send] ; Set sample end
- cmp [_si+channels.sampleType],smp16bit
- jne @@spl
- ; translate 16 bit sample address...
- mov edx,ecx
- shr ecx,1
- and ecx,01ffffh
- and edx,0c0000h
- xor ecx,edx
- @@spl:
- regsel 4 ; End position high
- inc _dx
- mov eax,ecx
- shr eax,7
- out dx,ax
- regsel 5 ; End position low
- inc _dx
- mov eax,ecx
- shl _ax,9
- out dx,ax
-
- mov ecx,[_si+channels.sstart] ; Set loop start
- cmp [_si+channels.sampleType],smp16bit
- jne @@spl2
- ; translate 16 bit sample address...
- mov edx,ecx
- shr ecx,1
- and ecx,01ffffh
- and edx,0c0000h
- xor ecx,edx
- @@spl2:
- regsel 2 ; Start position high
- inc _dx
- mov eax,ecx
- shr eax,7
- out dx,ax
- regsel 3 ; Start position low
- inc _dx
- mov eax,ecx
- shl _ax,9
- out dx,ax
-
- and [_si+channels.status],NOT gsSample
-
- @@not: regsel 0 ; Voice control
- add _dx,2
- mov al,3 ; Stop voice
- out dx,al
-
- mov ecx,[_si+channels.scurrent] ; Set starting address
- cmp [_si+channels.sampleType],smp16bit
- jne @@spl3
- ; translate 16 bit sample address...
- mov edx,ecx
- shr ecx,1
- and ecx,01ffffh
- and edx,0c0000h
- xor ecx,edx
- @@spl3:
- regsel 10 ; Current position high
- inc _dx
- mov eax,ecx
- shr eax,7
- out dx,ax
- regsel 11 ; Current position low
- inc _dx
- mov eax,ecx
- shl _ax,9
- out dx,ax
-
- call gusdelay
-
- out dx,ax
-
- regsel 10 ; Current position high
- inc _dx
- mov eax,ecx
- shr eax,7
- out dx,ax
-
- regsel 0 ; Voice control
- add _dx,2
- mov al,3 ; Stop voice
- out dx,al
-
- mov _ax,[_si+channels.inst]
- mov [_si+channels.curinst],_ax
-
- regsel 0 ; Voice control
- add dx,2
- mov _ax,[_si+channels.loop1Type] ; Enable voice and possible loop
- cmp _ax,loopNone
- je @@noloop2
- cmp _ax,loopUnidir
- je @@loopuni
-
- @@loopbidi:
- mov al,24
- jmp @@loopok2
- @@loopuni:
- mov al,8
- jmp @@loopok2
- @@noloop2:
- xor al,al
- @@loopok2:
- mov _cx,[_si+channels.sampleType]
- cmp _cx,smp16bit
- jne @@lok
- or al,4
- @@lok: out dx,al
-
- regsel 8 ; Ramp end
- add _dx,2
- mov _ax,[_si+channels.volume] ; To set volume
-
- test [_si+channels.status],gsMute
- jz @@oek
- xor _ax,_ax
- @@oek: mov _bx,[mastervol]
- mul bl
- shr _ax,6
- mov _bx,_ax
- add _bx,_bx
- mov ax,[voltable+_bx]
- mov al,ah
-
- cmp [_si+channels.surround],0
- je @@hu
- sub al,10h ; Halve the volume
- @@hu: out dx,al
-
- regsel 0dh
- add _dx,2
- xor al,al
- out dx,al
-
- call gusdelay ; Delay
-
- out dx,al
-
- regsel 0 ; Voice control
- add dx,2
- mov _ax,[_si+channels.loop1Type] ; Enable voice and possible loop
- cmp _ax,loopNone
- je @@noloop3
- cmp _ax,loopUnidir
- je @@loopuni2
- @@loopbidi2:
- mov al,24
- jmp @@loopok3
- @@loopuni2:
- mov al,8
- jmp @@loopok3
- @@noloop3:
- xor al,al
- @@loopok3:
- cmp _cx,smp16bit
- jne @@lok2
- or al,4
- @@lok2: out dx,al
-
- and [_si+channels.status],NOT (gsRetrig OR gsVolume)
-
- @@skip: add _si,size gusChannel ; Do all channels in order
- inc [chanc]
- mov _ax,[chancount]
- IFNDEF NOSTEREO
- cmp [mEnableSurround],0
- je @@ij2
- add _ax,_ax ; Plus Surround channels
- @@ij2:
- ENDIF
- cmp [chanc],_ax
- jb @@loop2
-
- IFE FASTGUS
- cmp [retrigfl],0 ; Still voices to wait?
- jne @@waitloop
- ENDIF
- mov _ax,[voicesave]
- mov _dx,[voicesel]
- out dx,al
-
- mov _ax,[selsave]
- mov _dx,[selreg]
- out dx,al
-
- mov [masterchanged],0
-
- LOADPTR es,_bx,[callMP]
- mov [_int _esbx],1 ; Call mp.Play!
- @@done: xor _ax,_ax
- ret
-
- @@paused:
- LOADPTR es,_bx,[callMP]
- mov [_int _esbx],0 ; Don't call mp.Play!
- jmp @@done
- ENDP
-
-
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int initHeap()
- ;*
- ;* Description: Initializes the GUS heap
- ;*
- ;* Returns: MIDAS error code.
- ;*
- ;\***************************************************************************/
-
-
- PROC initHeap NEAR
- USES _di,_bx
-
- mov _ax,MAXSAMPLES * SIZE ghb
-
- IFNDEF NOSTEREO
- cmp [mEnableSurround],0
- je @@kool
-
- add _ax,_ax ; Room for surround
- ; blocks, too
- @@kool:
- ENDIF
- push _ax
- call memAlloc LANG, _ax, ptr_to temp
- ; Alloc room for heap blocks
- pop _cx ; Size to _cx
- test _ax,_ax
- jne @@err
-
- mov ebx,[temp]
- mov [gusHeapStart],ebx
- mov [gusHeap],ebx
-
- LOADPTR es,_di,[temp]
- xor al,al
- ; Size already in _cx
- cld
- rep stosb ; Clear instrument datas
-
- LOADPTR es,_bx,[temp]
- mov eax,[memamount]
- mov [_esbx+ghb.next],0 ; first and last block
- mov [_esbx+ghb.gusmem],0 ; from the start of mem
- mov [_esbx+ghb.length],eax ; whole memory
- xor _ax,_ax
- ret
-
- @@err: ERROR ID_gusInitHeap
- ret
- ENDP
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int freeHeap()
- ;*
- ;* Description: Uninitializes the GUS heap
- ;*
- ;* Returns: MIDAS error code.
- ;*
- ;\***************************************************************************/
-
-
- PROC freeHeap NEAR
- USES _bx
-
- call memFree LANG, [gusHeap]
- test _ax,_ax
- jnz @@err
- ret
-
- @@err: ERROR ID_gusFreeHeap
- ret
- ENDP
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int gusMalloc(ushort length, ulong *mem)
- ;*
- ;* Description: Allocates GUS memory (with best fit alcorithm)
- ;*
- ;* Input: ushort length Length of the block to be allocated
- ;* (Rounded up to next 64 bytes with
- ;* at least 32 bytes for loop copy, etc.)
- ;*
- ;* Returns: MIDAS error code.
- ;*
- ;\***************************************************************************/
- PROC gusMalloc _funct glength : _int, gtype : _int, mem : _ptr
- USES _si,_di,_bx
- LOCAL bestfitoff : _int, bestfitseg : _int, leastslack : dword
-
- @@again:
- IFDEF __16__
- xor eax,eax
- ENDIF
- mov _ax,[glength]
- test _ax,_ax
- jz @@done
-
- mov ebx,eax ; Round up to next 64 byte border
- and ebx,1fh ; with at least 32 bytes buffer
- mov ecx,64
- sub ecx,ebx
- add eax,ecx
-
- cmp eax,256*1024
- jb @@mok
-
- cmp [gtype],smp16bit
- je @@notenoughmem ; can't play over 256kb
- ; 16-; bit samples...
- @@mok: mov [bestfitseg],0
- mov [leastslack],7ffffffh
-
- cmp [memavail],eax ; Is there that much memory left
- jl @@notenoughmem
-
- cmp [largestblock],eax ; Do we have to defragment?
- jg @@noneedtodefragment
-
- push eax
- call gusDefragment
- pop eax
-
- cmp [largestblock],eax
- jl @@notenoughmem
-
- @@noneedtodefragment:
- LOADPTR es,_si,[gusHeapStart]
-
- @@findbest:
- push eax
- call findFreeBlock
- pop eax
- jc @@notanymore
-
- mov ebx,[_essi+ghb.length]
- and ebx, NOT 1fh ; And flags off
- sub ebx,eax
- js @@nxt ; Too small
-
- cmp [leastslack],ebx
- jl @@nxt ; Not the best
-
- mov [leastslack],ebx ; Set to be the best
- IFDEF __16__
- mov _bx,es
- mov [bestfitseg],_bx
- ENDIF
- mov [bestfitoff],_si
-
- @@nxt:
- mov ecx,[_essi+ghb.next] ; Advance to next block
- test ecx,ecx
- jz @@notanymore
- mov _si,_cx
- IFDEF __16__
- shr ecx,16
- mov es,cx
- ENDIF
- jmp @@findbest
-
- @@notanymore:
- IFDEF __16__
- cmp [bestfitseg],0 ; Was there any free blocks large enough?
- je @@notenoughmem
- ELSE
- cmp [bestfitoff],0 ; Was there any free blocks large enough?
- je @@notenoughmem
- ENDIF
- cmp [leastslack],0
- je @@justalloc
-
- @@notfit:
- push eax
- call allocBlock LANG, ptr_to temp ; Allocate new block
- test _ax,_ax
- jnz @@memerr
-
- pop eax
- LOADPTR gs,_di,[temp]
-
- mov _si,[bestfitoff]
- IFDEF __16__
- mov bx,[bestfitseg]
- mov es,bx
- ENDIF
- mov ebx,[_essi+ghb.gusmem] ; Copy pointer
-
- cmp [gtype],smp16bit
- jne @@kool
-
- mov ecx,ebx
- mov edx,ecx
- add ecx,eax
- and ecx,NOT(256*1024-1)
- and edx,NOT(256*1024-1)
- cmp ecx,edx
- je @@kool ; Wholly inside one
- ; 256k bank
-
- ; We'll have to split this block to two, one for each bank.
- @@split:
- mov ecx,ebx
- add ecx,256*1024-1
- and ecx,NOT (256*1024-1)
- mov [_gsdi+ghb.gusmem],ecx
- sub ecx,ebx
- mov ebx,[_essi+ghb.length]
- sub ebx,ecx
- mov [_gsdi+ghb.length],ebx ; second block length
- mov [_essi+ghb.length],ecx ; first block length
- mov ecx,[_essi+ghb.next]
- mov ebx,[temp]
- mov [_gsdi+ghb.next],ecx
- mov [_essi+ghb.next],ebx
-
- PUSHSEGREG gs
- call checkCoreFree ; Update biggest block
- POPSEGREG gs
- test _ax,_ax
- jnz @@err
- jmp @@again
-
- @@kool:
- mov [_gsdi+ghb.gusmem],ebx
- mov [_gsdi+ghb.length],eax ; Set block length
- or [_gsdi+ghb.length],1 ; Mark as allocated
-
- add [_essi+ghb.gusmem],eax ; Move free block "upwards"
- sub [_essi+ghb.length],eax ; Sub free block length
-
- IFDEF __16__
- mov bx,es
- shl ebx,16
- ENDIF
- mov _bx,_si
-
- mov [_gsdi+ghb.next],ebx ; Link blocks
- cmp [gusHeapStart],ebx
- jne @@notfirst ; The first block?
-
- IFDEF __16__
- mov bx,gs ; Set this block to HeapStart
- shl ebx,16
- ENDIF
- mov _bx,_di
- mov [gusHeapStart],ebx
- jmp @@donee
-
- @@notfirst:
- push eax
- mov eax,ebx
- call findPrevBlock ; Find block linked to the free block
- pop eax
- jc @@heapcorr ; No such block!
-
- IFDEF __16__
- mov bx,gs
- shl ebx,16
- ENDIF
- mov _bx,_di
- mov [_essi+ghb.next],ebx ; Link to previous block
-
-
- @@donee:
- sub [memavail],eax
- PUSHSEGREG gs
- call checkCoreFree ; Update biggest block
- POPSEGREG gs
- test _ax,_ax
- jnz @@err
- mov eax,[_gsdi+ghb.gusmem] ; Return pointer
- LOADPTR es,_bx,[mem]
- mov [_esbx],eax
- xor _ax,_ax
- ret
-
- @@justalloc: ; Realloc?
- mov ebx,[_essi+ghb.gusmem] ; Copy pointer
-
- cmp [gtype],smp16bit
- jne @@kool2
-
- mov ecx,ebx
- mov edx,ecx
- add ecx,eax
- and ecx,NOT(256*1024-1)
- and edx,NOT(256*1024-1)
- cmp ecx,edx
- jne @@notfit ; we'll have to split...
- @@kool2:
- or [_essi+ghb.length],1
- sub [memavail],eax
- PUSHSEGREG es
- call checkCoreFree
- POPSEGREG es
- test _ax,_ax
- jnz @@err
- mov eax,[_essi+ghb.gusmem]
- @@done: LOADPTR es,_bx,[mem]
- mov [_esbx],eax
- xor _ax,_ax
- ret
-
- @@memerr:
- pop ebx ; pop saved pointer
- jmp @@err
-
- @@heapcorr:
- mov _ax,errCardHeapCorrupted
- jmp @@err
-
- @@notenoughmem:
- mov _ax,errOutOfCardMemory
- @@err: ERROR ID_gusMalloc
- ret
- ENDP
-
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int gusFree(ulong mem)
- ;*
- ;* Description: Deallocates GUS memory
- ;*
- ;* Input: ulong block Pointer to allocated GUS mem
- ;*
- ;* Returns: 1 if success, 0 if not
- ;*
- ;* Destroys: ax, bx, cx, dx
- ;*
- ;\***************************************************************************/
- PROC gusFree _funct block : dword
- USES _si,_di,_bx
- LOCAL freed : dword
-
- mov eax,[block]
-
- LOADPTR gs,_di,[gusHeapStart]
- @@sloop:
- cmp [_gsdi+ghb.gusmem],eax
- je @@found
-
- mov ebx,[_gsdi+ghb.next]
- test ebx,ebx
- jz @@invalid
- mov _di,_bx
- IFDEF __16__
- shr ebx,16
- mov gs,bx
- ENDIF
- jmp @@sloop
-
- @@found:
- test [_gsdi+ghb.length],1
- jz @@heapcorr ; Not even allocated
-
- and [_gsdi+ghb.length],NOT 1 ; Free this block
-
- mov ebx,[_gsdi+ghb.length]
- mov [freed],ebx
-
- mov ebx,[_gsdi+ghb.next]
- test ebx,ebx
- jz @@nonextblock ; Last block
-
- mov _si,_bx
- IFDEF __16__
- shr ebx,16
- mov es,bx
- ENDIF
- test [_essi+ghb.length],1
- jnz @@nonextblock ; Next allocated -> Can't merge blocks
-
- mov edx,[_essi+ghb.next]
- mov [_gsdi+ghb.next],edx
- mov edx,[_essi+ghb.length] ; Merge blocks
- add [_gsdi+ghb.length],edx
-
- PUSHSEGREG gs
- IFDEF __16__
- call freeBlock LANG, es si ; Free block
- ELSE
- call freeBlock LANG, esi ; Free block
- ENDIF
- POPSEGREG gs
- test _ax,_ax
- jnz @@err
-
- @@nonextblock:
- IFDEF __16__
- mov bx,gs
- shl ebx,16
- ENDIF
- mov _bx,_di
- cmp [gusHeapStart],ebx
- je @@firstblock ; First block
-
- mov eax,ebx
- call findPrevBlock
- jc @@heapcorr ; No such block! (Heap corrupt?)
-
- test [_essi+ghb.length],1
- jnz @@firstblock ; previous allocated -> can't merge blocks
-
- mov edx,[_gsdi+ghb.next]
- mov [_essi+ghb.next],edx
- mov edx,[_gsdi+ghb.length] ; Merge blocks
- add [_essi+ghb.length],edx
-
- IFDEF __16__
- call freeBlock LANG, gs di ; Free block
- ELSE
- call freeBlock LANG, edi ; Free block
- ENDIF
- test _ax,_ax
- jnz @@err
-
- @@firstblock:
- mov eax,[freed]
- add [memavail],eax
- call checkCoreFree
- test _ax,_ax
- jnz @@err
- xor _ax,_ax
- ret
-
- @@heapcorr:
- mov _ax,errCardHeapCorrupted
- jmp @@err
-
- @@invalid:
- mov _ax,errInvalidBlock
- @@err: ERROR ID_gusFree
- ret
- ENDP
-
-
- PROC allocBlock NEAR block : _ptr
- uses _bx
-
- LOADPTR es,_bx,[gusHeapStart]
- mov _cx,MAXSAMPLES
- cmp [mEnableSurround],0
- je @@findloop
- add _cx,_cx ; Include surround blocks
- @@findloop:
- cmp [_esbx+ghb.length],0
- je @@found
- add _bx,size ghb
- dec _cx
- jnz @@findloop
- jmp @@err
- @@found:
- IFDEF __16__
- mov ax,es
- shl eax,16
- ENDIF
- mov _ax,_bx
- LOADPTR es,_bx,[block]
- mov [_esbx],eax
- xor _ax,_ax
- ret
-
- @@err: mov _ax,errInvalidBlock
- ERROR ID_gusAllocBlock
- ret
- ENDP
-
- PROC freeBlock NEAR block : _ptr
- USES _bx
-
- LOADPTR es,_bx,[block]
- mov [_esbx+ghb.next],0
- mov [_esbx+ghb.gusmem],0
- mov [_esbx+ghb.length],0
- xor _ax,_ax
- ret
- ENDP
-
- ; _essi = pointer to current block
- ; Returns: _essi = next free block
- ; Carry set if not found
-
- PROC findFreeBlock NEAR
-
- @@sloop:
- test [_essi+ghb.length],1
- jz @@found
-
- mov eax,[_essi+ghb.next] ; Advance to next block
- test eax,eax
- jz @@nofree
- mov _si,_ax
- IFDEF __16__
- shr eax,16
- mov es,ax
- ENDIF
- jmp @@sloop
-
- @@found:
- clc
- ret
- @@nofree:
- stc
- ret
- ENDP
-
-
- ; eax = pointer to current block
- ; Returns: _essi = prev block
- ; Carry set if not found
-
- PROC findPrevBlock NEAR
-
- LOADPTR es,_si,[gusHeapStart]
- @@sloop:
- cmp [_essi+ghb.next],eax
- je @@found
-
- mov ebx,[_essi+ghb.next]
- test ebx,ebx
- jz @@done
- mov _si,_bx
- IFDEF __16__
- shr ebx,16
- mov es,bx
- ENDIF
- jmp @@sloop
-
- @@found:
- clc
- ret
- @@done:
- stc
- ret
- ENDP
-
-
-
- ; No parameters, also checks heap integrity
- ; Returns MIDAS error code
-
- PROC checkCoreFree NEAR
- USES _si,_bx
-
- LOADPTR es,_si,[gusHeapStart]
- xor edx,edx ; Start from size 0
- xor ecx,ecx ; Total mem size
- @@findloop:
- mov eax,[_essi+ghb.length]
- mov ebx,eax
- and ebx,NOT 31 ; ebx = size
- add ecx,ebx ; Add to total
- test eax,1 ; Allocated flag
- jnz @@findnext ; Allocated
- cmp ebx,edx ; Largest?
- jle @@findnext
- mov edx,ebx
- @@findnext:
- mov eax,[_essi+ghb.next] ; Advance to next block
- test eax,eax
- jz @@done
- mov _si,_ax
- IFDEF __16__
- shr eax,16
- mov es,ax
- ENDIF
- jmp @@findloop
-
- @@done: mov [largestblock],edx
- cmp [memamount],ecx ; All memory in heap?
- jne @@heapcorr ; heap corrupt!
- xor _ax,_ax
- ret
-
- @@heapcorr:
- mov _ax,errCardHeapCorrupted
- ERROR ID_gusCoreFree
- ret
- ENDP
-
- ;/***************************************************************************\
- ;*
- ;* Function: gusDefragment
- ;*
- ;* Description: Defragments the GUS memory
- ;*
- ;\***************************************************************************/
- PROC gusDefragment _funct
- ret
- ENDP
-
-
- ;* $Log: gus.asm,v $
- ;* Revision 1.3 1997/01/16 18:41:59 pekangas
- ;* Changed copyright messages to Housemarque
- ;*
- ;* Revision 1.2 1996/08/04 11:27:42 pekangas
- ;* All functions now preserve _bx
- ;*
- ;* Revision 1.1 1996/05/22 20:49:33 pekangas
- ;* Initial revision
- ;*
-
-
- END